1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
42 #include <modest-account-mgr.h>
43 #include <modest-account-mgr-helpers.h>
45 #include <widgets/modest-msg-edit-window.h>
46 #include <widgets/modest-combo-box.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <wptextview.h>
65 #include <wptextbuffer.h>
66 #include "modest-scroll-area.h"
67 #include "modest-msg-edit-window-ui-dimming.h"
69 #include "modest-hildon-includes.h"
70 #ifdef MODEST_HAVE_HILDON0_WIDGETS
71 #include <hildon-widgets/hildon-color-chooser.h>
73 #include "widgets/modest-msg-edit-window-ui.h"
74 #ifdef MODEST_HAVE_HILDON0_WIDGETS
75 #include <libgnomevfs/gnome-vfs-mime-utils.h>
77 #include <libgnomevfs/gnome-vfs-mime.h>
79 #include <modest-utils.h>
80 #include "modest-maemo-utils.h"
83 #define DEFAULT_FONT_SIZE 3
84 #define DEFAULT_FONT 2
85 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
86 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
87 #define DEFAULT_MAIN_VBOX_SPACING 6
88 #define SUBJECT_MAX_LENGTH 1000
89 #define IMAGE_MAX_WIDTH 560
90 #define DEFAULT_FONT_SCALE 1.5
92 static gboolean is_wp_text_buffer_started = FALSE;
94 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
95 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
96 static void modest_msg_edit_window_finalize (GObject *obj);
98 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
99 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
100 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
102 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
103 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
104 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
105 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
106 GtkTextIter *start, GtkTextIter *end,
108 static void text_buffer_insert_text (GtkTextBuffer *buffer,
109 GtkTextIter *location,
112 ModestMsgEditWindow *window);
113 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
114 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
115 static void subject_field_insert_text (GtkEditable *editable,
117 gint new_text_length,
119 ModestMsgEditWindow *window);
120 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
122 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
124 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
126 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
127 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
128 GdkEventWindowState *event,
130 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
131 ModestRecptEditor *editor);
132 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
133 ModestMsgEditWindow *window);
135 /* ModestWindow methods implementation */
136 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
137 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
138 gboolean show_toolbar);
139 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
141 ModestMsgEditWindow *window);
142 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
143 static void subject_field_move_cursor (GtkEntry *entry,
144 GtkMovementStep step,
148 static void update_window_title (ModestMsgEditWindow *window);
151 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
152 ModestMsgEditWindow *window);
153 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
154 ModestMsgEditWindow *window);
155 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
157 GtkTextIter *match_start,
158 GtkTextIter *match_end);
160 static void remove_tags (WPTextBuffer *buffer);
162 static void on_account_removed (TnyAccountStore *account_store,
166 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
167 static void set_zoom_do_nothing (ModestWindow *window, gdouble zoom);
168 static gdouble get_zoom_do_nothing (ModestWindow *window);
170 static void init_window (ModestMsgEditWindow *obj);
172 gboolean scroll_drag_timeout (gpointer userdata);
173 static void correct_scroll (ModestMsgEditWindow *w);
174 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
175 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
176 ModestMsgEditWindow *userdata);
177 static void text_buffer_mark_set (GtkTextBuffer *buffer,
180 ModestMsgEditWindow *userdata);
181 void vadj_changed (GtkAdjustment *adj,
182 ModestMsgEditWindow *window);
184 static void DEBUG_BUFFER (WPTextBuffer *buffer)
188 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
190 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
191 while (!gtk_text_iter_is_end (&iter)) {
192 GString *output = g_string_new ("");
193 GSList *toggled_tags;
196 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
197 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
198 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
199 GtkTextTag *tag = (GtkTextTag *) node->data;
201 g_object_get (G_OBJECT (tag), "name", &name, NULL);
202 output = g_string_append (output, name);
203 g_string_append (output, " ");
205 output = g_string_append (output, "] OPENED [ ");
206 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
207 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
208 GtkTextTag *tag = (GtkTextTag *) node->data;
210 g_object_get (G_OBJECT (tag), "name", &name, NULL);
211 output = g_string_append (output, name);
212 g_string_append (output, " ");
214 output = g_string_append (output, "]\n");
215 g_message ("%s", output->str);
216 g_string_free (output, TRUE);
217 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
219 g_message ("END BUFFER");
224 /* static gboolean */
225 /* on_key_pressed (GtkWidget *self, */
226 /* GdkEventKey *event, */
227 /* gpointer user_data); */
229 /* list my signals */
236 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
237 struct _ModestMsgEditWindowPrivate {
240 GtkWidget *header_box;
242 ModestPairList *from_field_protos;
243 GtkWidget *from_field;
244 gchar *original_account_name;
248 GtkWidget *bcc_field;
249 GtkWidget *subject_field;
250 GtkWidget *attachments_view;
251 GtkWidget *priority_icon;
252 GtkWidget *add_attachment_button;
254 GtkWidget *cc_caption;
255 GtkWidget *bcc_caption;
256 gboolean update_caption_visibility;
257 GtkWidget *attachments_caption;
259 GtkTextBuffer *text_buffer;
261 GtkWidget *font_size_toolitem;
262 GtkWidget *font_face_toolitem;
263 GtkWidget *font_color_button;
264 GSList *font_items_group;
265 GtkWidget *font_tool_button_label;
266 GSList *size_items_group;
267 GtkWidget *size_tool_button_label;
269 GtkWidget *find_toolbar;
272 GtkWidget *font_dialog;
275 guint scroll_drag_timeout_id;
279 TnyList *attachments;
284 TnyHeaderFlags priority_flags;
286 gboolean can_undo, can_redo;
287 gulong clipboard_change_handler_id;
288 gulong default_clipboard_change_handler_id;
289 gulong account_removed_handler_id;
290 guint clipboard_owner_idle;
291 gchar *clipboard_text;
300 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
301 MODEST_TYPE_MSG_EDIT_WINDOW, \
302 ModestMsgEditWindowPrivate))
304 static GtkWindowClass *parent_class = NULL;
306 /* uncomment the following if you have defined any signals */
307 /* static guint signals[LAST_SIGNAL] = {0}; */
310 modest_msg_edit_window_get_type (void)
312 static GType my_type = 0;
314 static const GTypeInfo my_info = {
315 sizeof(ModestMsgEditWindowClass),
316 NULL, /* base init */
317 NULL, /* base finalize */
318 (GClassInitFunc) modest_msg_edit_window_class_init,
319 NULL, /* class finalize */
320 NULL, /* class data */
321 sizeof(ModestMsgEditWindow),
323 (GInstanceInitFunc) modest_msg_edit_window_init,
326 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
327 "ModestMsgEditWindow",
335 save_state (ModestWindow *self)
337 modest_widget_memory_save (modest_runtime_get_conf(),
338 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
343 restore_settings (ModestMsgEditWindow *self)
345 ModestConf *conf = NULL;
347 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
349 conf = modest_runtime_get_conf ();
350 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
351 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
352 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
353 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL));
354 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
355 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu");
356 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
357 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
359 /* set initial state of cc and bcc */
360 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
361 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
362 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
363 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
364 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
365 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
367 /* Dim at start clipboard actions */
368 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
369 gtk_action_set_sensitive (action, FALSE);
370 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
371 gtk_action_set_sensitive (action, FALSE);
372 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
373 gtk_action_set_sensitive (action, FALSE);
375 modest_widget_memory_restore (conf,
376 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
381 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
383 GObjectClass *gobject_class;
384 ModestWindowClass *modest_window_class;
385 gobject_class = (GObjectClass*) klass;
386 modest_window_class = (ModestWindowClass*) klass;
388 parent_class = g_type_class_peek_parent (klass);
389 gobject_class->finalize = modest_msg_edit_window_finalize;
391 modest_window_class->set_zoom_func = set_zoom_do_nothing;
392 modest_window_class->get_zoom_func = get_zoom_do_nothing;
393 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
394 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
395 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
396 modest_window_class->save_state_func = save_state;
397 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
399 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
403 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
405 ModestMsgEditWindowPrivate *priv;
406 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
408 priv->msg_body = NULL;
410 priv->from_field = NULL;
411 priv->to_field = NULL;
412 priv->cc_field = NULL;
413 priv->bcc_field = NULL;
414 priv->subject_field = NULL;
415 priv->attachments = TNY_LIST (tny_simple_list_new ());
416 priv->images = TNY_LIST (tny_simple_list_new ());
417 priv->images_size = 0;
418 priv->images_count = 0;
421 priv->cc_caption = NULL;
422 priv->bcc_caption = NULL;
423 priv->update_caption_visibility = FALSE;
425 priv->priority_flags = 0;
427 priv->find_toolbar = NULL;
428 priv->last_search = NULL;
430 priv->draft_msg = NULL;
431 priv->outbox_msg = NULL;
432 priv->msg_uid = NULL;
434 priv->can_undo = FALSE;
435 priv->can_redo = FALSE;
436 priv->clipboard_change_handler_id = 0;
437 priv->default_clipboard_change_handler_id = 0;
438 priv->account_removed_handler_id = 0;
439 priv->clipboard_owner_idle = 0;
440 priv->clipboard_text = NULL;
443 priv->scroll_drag_timeout_id = 0;
444 priv->last_upper = 0.0;
446 priv->font_dialog = NULL;
448 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
449 GTK_WINDOW(obj),"applications_email_editor");
451 if (!is_wp_text_buffer_started) {
452 is_wp_text_buffer_started = TRUE;
453 wp_text_buffer_library_init ();
458 hildon_program_add_window (hildon_program_get_instance(),
463 /* FIXME: this is a dup from the one in gtk/ */
466 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
468 static ModestPairList*
469 get_transports (void)
471 GSList *transports = NULL;
473 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
474 GSList *accounts = modest_account_mgr_account_names (account_mgr,
475 TRUE /* only enabled accounts. */);
477 GSList *cursor = accounts;
479 gchar *account_name = cursor->data;
480 gchar *from_string = NULL;
482 from_string = modest_account_mgr_get_from_string (account_mgr,
486 if (from_string && account_name) {
487 gchar *name = account_name;
488 ModestPair *pair = modest_pair_new ((gpointer) name,
489 (gpointer) from_string , TRUE);
490 transports = g_slist_prepend (transports, pair);
493 cursor = cursor->next;
495 g_slist_free (accounts); /* only free the accounts, not the elements,
496 * because they are used in the pairlist */
500 static void window_focus (GtkWindow *window,
504 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
508 scroll_drag_timeout (gpointer userdata)
510 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
511 ModestMsgEditWindowPrivate *priv;
513 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
515 correct_scroll_without_drag_check (win, TRUE);
517 priv->scroll_drag_timeout_id = 0;
523 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
525 ModestMsgEditWindowPrivate *priv;
528 GdkRectangle rectangle;
534 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
536 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
539 insert = gtk_text_buffer_get_insert (priv->text_buffer);
540 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
542 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
543 vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll));
544 offset = priv->msg_body->allocation.y;
546 new_value = vadj->value;
548 if ((offset + rectangle.y + rectangle.height) >
549 ((gint) (vadj->value +vadj->page_size))) {
550 new_value = (offset + rectangle.y) - vadj->page_size * 0.25;
551 if (new_value > vadj->upper - vadj->page_size)
552 new_value = vadj->upper - vadj->page_size;
553 } else if ((offset + rectangle.y) < ((gint) vadj->value)) {
554 new_value = (offset + rectangle.y - vadj->page_size * 0.75);
555 if (((gint) (new_value + vadj->page_size)) < (offset + rectangle.y + rectangle.height))
556 new_value = offset + rectangle.y + rectangle.height - (gint) vadj->page_size;
559 if (new_value > vadj->value)
560 new_value = vadj->value;
563 if (vadj->value != new_value) {
564 g_signal_emit_by_name (GTK_TEXT_VIEW(priv->msg_body)->layout,
566 vadj->value = new_value;
567 gtk_adjustment_value_changed (vadj);
568 /* invalidate body */
569 window = gtk_widget_get_parent_window (priv->msg_body);
571 gdk_window_invalidate_rect (window, NULL, TRUE);
577 correct_scroll (ModestMsgEditWindow *w)
579 ModestMsgEditWindowPrivate *priv;
581 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
582 if (gtk_grab_get_current () == priv->msg_body) {
583 if (priv->scroll_drag_timeout_id == 0) {
584 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
590 correct_scroll_without_drag_check (w, TRUE);
594 text_buffer_end_user_action (GtkTextBuffer *buffer,
595 ModestMsgEditWindow *userdata)
598 correct_scroll (userdata);
602 text_buffer_mark_set (GtkTextBuffer *buffer,
605 ModestMsgEditWindow *userdata)
607 gtk_text_buffer_begin_user_action (buffer);
608 gtk_text_buffer_end_user_action (buffer);
612 cut_clipboard_check (GtkTextView *text_view,
615 GtkTextBuffer *buffer;
617 buffer = gtk_text_view_get_buffer (text_view);
618 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
619 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
624 copy_clipboard_check (GtkTextView *text_view,
627 GtkTextBuffer *buffer;
629 buffer = gtk_text_view_get_buffer (text_view);
630 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
631 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
635 void vadj_changed (GtkAdjustment *adj,
636 ModestMsgEditWindow *window)
638 ModestMsgEditWindowPrivate *priv;
640 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
642 if (priv->last_upper != adj->upper) {
643 priv->last_upper = adj->upper;
644 correct_scroll (window);
649 connect_signals (ModestMsgEditWindow *obj)
651 ModestMsgEditWindowPrivate *priv;
653 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
655 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
656 G_CALLBACK (text_buffer_refresh_attributes), obj);
657 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
658 G_CALLBACK (text_buffer_can_undo), obj);
659 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
660 G_CALLBACK (text_buffer_can_redo), obj);
661 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
662 G_CALLBACK (body_changed), obj);
663 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
664 G_CALLBACK (body_changed), obj);
665 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
666 G_CALLBACK (text_buffer_insert_text), obj);
667 g_signal_connect (G_OBJECT (obj), "window-state-event",
668 G_CALLBACK (modest_msg_edit_window_window_state_event),
670 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
671 G_CALLBACK (text_buffer_end_user_action), obj);
672 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
673 G_CALLBACK (text_buffer_mark_set), obj);
674 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
675 G_CALLBACK (text_buffer_apply_tag), obj);
676 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
677 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
678 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
679 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
680 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
681 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
683 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
684 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
686 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
687 G_CALLBACK (msg_body_focus), obj);
688 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
689 G_CALLBACK (msg_body_focus), obj);
690 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
691 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
692 "changed", G_CALLBACK (recpt_field_changed), obj);
693 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
694 "changed", G_CALLBACK (recpt_field_changed), obj);
695 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
696 "changed", G_CALLBACK (recpt_field_changed), obj);
697 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
698 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
699 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
701 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
702 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
704 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
706 G_CALLBACK (vadj_changed),
709 priv->clipboard_change_handler_id =
710 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
711 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
712 priv->default_clipboard_change_handler_id =
713 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
714 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
716 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
717 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
722 init_window (ModestMsgEditWindow *obj)
724 GtkWidget *from_caption, *to_caption, *subject_caption;
725 GtkWidget *main_vbox;
726 ModestMsgEditWindowPrivate *priv;
727 GtkActionGroup *action_group;
728 ModestWindowPrivate *parent_priv;
729 GdkPixbuf *window_icon = NULL;
730 GError *error = NULL;
732 GtkSizeGroup *size_group;
733 GtkWidget *subject_box;
734 GtkWidget *attachment_icon;
735 GtkWidget *window_box;
736 #if (GTK_MINOR_VERSION >= 10)
737 GdkAtom deserialize_type;
739 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
740 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
742 parent_priv->ui_manager = gtk_ui_manager_new();
743 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
744 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
746 /* Add common actions */
747 gtk_action_group_add_actions (action_group,
748 modest_msg_edit_action_entries,
749 G_N_ELEMENTS (modest_msg_edit_action_entries),
751 gtk_action_group_add_toggle_actions (action_group,
752 modest_msg_edit_toggle_action_entries,
753 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
755 gtk_action_group_add_radio_actions (action_group,
756 modest_msg_edit_alignment_radio_action_entries,
757 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
759 G_CALLBACK (modest_ui_actions_on_change_justify),
761 gtk_action_group_add_radio_actions (action_group,
762 modest_msg_edit_priority_action_entries,
763 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
765 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
767 gtk_action_group_add_radio_actions (action_group,
768 modest_msg_edit_file_format_action_entries,
769 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
770 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
771 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
773 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
774 g_object_unref (action_group);
776 /* Load the UI definition */
777 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
780 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
781 g_clear_error (&error);
784 /* Add accelerators */
785 gtk_window_add_accel_group (GTK_WINDOW (obj),
786 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
788 parent_priv->menubar = NULL;
790 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
792 /* Note: This ModestPairList* must exist for as long as the combo
793 * that uses it, because the ModestComboBox uses the ID opaquely,
794 * so it can't know how to manage its memory. */
795 priv->from_field = modest_combo_box_new (NULL, g_str_equal);
797 priv->to_field = modest_recpt_editor_new ();
798 priv->cc_field = modest_recpt_editor_new ();
799 priv->bcc_field = modest_recpt_editor_new ();
800 subject_box = gtk_hbox_new (FALSE, 0);
801 priv->priority_icon = gtk_image_new ();
802 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
803 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
804 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
805 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
806 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
807 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
808 priv->add_attachment_button = gtk_button_new ();
809 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
810 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
811 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
812 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
813 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
814 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
815 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
816 priv->attachments_view = modest_attachments_view_new (NULL);
818 priv->header_box = gtk_vbox_new (FALSE, 0);
820 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
821 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
822 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
823 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
824 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
825 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
826 g_object_unref (size_group);
828 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
829 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
830 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
831 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
832 gtk_size_group_add_widget (size_group, priv->subject_field);
833 gtk_size_group_add_widget (size_group, priv->attachments_view);
834 g_object_unref (size_group);
836 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
837 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
838 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
839 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
840 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
841 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
842 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
845 priv->msg_body = wp_text_view_new ();
846 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
847 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
848 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
849 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
850 #if (GTK_MINOR_VERSION >= 10)
851 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
852 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
854 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
855 deserialize_type, TRUE);
857 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
859 priv->find_toolbar = hildon_find_toolbar_new (NULL);
860 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
862 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
864 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
865 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
866 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
867 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
869 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
871 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
872 priv->frame = gtk_frame_new (NULL);
873 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
875 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
876 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
877 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
879 window_box = gtk_vbox_new (FALSE, 0);
880 gtk_container_add (GTK_CONTAINER(obj), window_box);
882 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
884 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
886 /* Set window icon */
887 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
889 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
890 g_object_unref (window_icon);
895 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
897 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
899 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
900 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
901 priv->clipboard_change_handler_id))
902 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
903 priv->clipboard_change_handler_id);
904 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
905 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
906 priv->default_clipboard_change_handler_id))
907 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
908 priv->default_clipboard_change_handler_id);
910 if (priv->account_removed_handler_id &&
911 g_signal_handler_is_connected (modest_runtime_get_account_store (),
912 priv->account_removed_handler_id))
913 g_signal_handler_disconnect(modest_runtime_get_account_store (),
914 priv->account_removed_handler_id);
918 modest_msg_edit_window_finalize (GObject *obj)
920 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
922 /* Sanity check: shouldn't be needed, the window mgr should
923 call this function before */
924 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
926 if (priv->font_dialog != NULL) {
927 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
930 if (priv->clipboard_text != NULL) {
931 g_free (priv->clipboard_text);
932 priv->clipboard_text = NULL;
935 if (priv->draft_msg != NULL) {
936 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
937 if (TNY_IS_HEADER (header)) {
938 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
939 modest_window_mgr_unregister_header (mgr, header);
941 g_object_unref (priv->draft_msg);
942 priv->draft_msg = NULL;
944 if (priv->outbox_msg != NULL) {
945 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
946 if (TNY_IS_HEADER (header)) {
947 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
948 modest_window_mgr_unregister_header (mgr, header);
950 g_object_unref (priv->outbox_msg);
951 priv->outbox_msg = NULL;
953 if (priv->scroll_drag_timeout_id > 0) {
954 g_source_remove (priv->scroll_drag_timeout_id);
955 priv->scroll_drag_timeout_id = 0;
957 if (priv->clipboard_owner_idle > 0) {
958 g_source_remove (priv->clipboard_owner_idle);
959 priv->clipboard_owner_idle = 0;
961 if (priv->original_account_name)
962 g_free (priv->original_account_name);
963 g_free (priv->msg_uid);
964 g_free (priv->last_search);
965 g_slist_free (priv->font_items_group);
966 g_slist_free (priv->size_items_group);
967 g_object_unref (priv->attachments);
968 g_object_unref (priv->images);
970 /* This had to stay alive for as long as the combobox that used it: */
971 modest_pair_list_free (priv->from_field_protos);
973 G_OBJECT_CLASS(parent_class)->finalize (obj);
977 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
979 GdkPixbufLoader *loader;
985 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
987 if (loader == NULL) {
993 tny_stream_reset (TNY_STREAM (stream));
994 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
995 GError *error = NULL;
996 unsigned char read_buffer[128];
998 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1000 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1005 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1007 g_object_ref (pixbuf);
1008 gdk_pixbuf_loader_close (loader, NULL);
1009 g_object_unref (loader);
1014 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1015 GdkPixbuf *new_pixbuf;
1017 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1018 gdk_pixbuf_get_width (pixbuf);
1019 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1020 g_object_unref (pixbuf);
1021 pixbuf = new_pixbuf;
1025 *stream_size = size;
1031 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1033 ModestMsgEditWindowPrivate *priv;
1036 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1038 for (iter = tny_list_create_iterator (attachments);
1039 !tny_iterator_is_done (iter);
1040 tny_iterator_next (iter)) {
1041 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1042 const gchar *cid = tny_mime_part_get_content_id (part);
1043 const gchar *mime_type = tny_mime_part_get_content_type (part);
1044 if ((cid != NULL)&&(mime_type != NULL)) {
1045 guint64 stream_size;
1046 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1047 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1050 g_object_unref (stream);
1052 if (pixbuf != NULL) {
1053 priv->images_count ++;
1054 priv->images_size += stream_size;
1055 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1056 g_object_unref (pixbuf);
1059 g_object_unref (part);
1061 g_object_unref (iter);
1065 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1067 TnyMimePart *parent = NULL;
1068 const gchar *content_type = NULL;
1069 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1071 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1073 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1074 parent = g_object_ref (msg);
1075 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1076 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1079 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1080 iter = tny_list_create_iterator (parts);
1081 while (!tny_iterator_is_done (iter)) {
1083 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1084 content_type = tny_mime_part_get_content_type (part);
1085 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1089 g_object_unref (part);
1091 tny_iterator_next (iter);
1093 g_object_unref (iter);
1094 g_object_unref (parts);
1097 if (parent != NULL) {
1098 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1101 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1102 iter = tny_list_create_iterator (parts);
1103 while (!tny_iterator_is_done (iter)) {
1105 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1106 content_type = tny_mime_part_get_content_type (part);
1107 if (content_type && g_str_has_prefix (content_type, "image/")) {
1108 tny_list_prepend (priv->images, (GObject *) part);
1110 g_object_unref (part);
1111 tny_iterator_next (iter);
1113 g_object_unref (iter);
1114 g_object_unref (parts);
1115 g_object_unref (parent);
1120 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1123 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1125 for (iter = tny_list_create_iterator (attachments) ;
1126 !tny_iterator_is_done (iter);
1127 tny_iterator_next (iter)) {
1128 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1129 const gchar *cid = tny_mime_part_get_content_id (part);
1131 char *invalid = NULL;
1132 gint int_cid = strtol (cid, &invalid, 10);
1133 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1134 priv->next_cid = int_cid + 1;
1137 g_object_unref (part);
1139 g_object_unref (iter);
1143 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1146 gchar *to, *cc, *bcc, *subject;
1148 ModestMsgEditWindowPrivate *priv;
1150 TnyHeaderFlags priority_flags;
1151 TnyFolder *msg_folder;
1152 gboolean is_html = FALSE;
1154 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1155 g_return_if_fail (TNY_IS_MSG (msg));
1157 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1159 header = tny_msg_get_header (msg);
1160 to = tny_header_dup_to (header);
1161 cc = tny_header_dup_cc (header);
1162 bcc = tny_header_dup_bcc (header);
1163 subject = tny_header_dup_subject (header);
1164 priority_flags = tny_header_get_priority (header);
1167 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1169 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1170 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1171 gtk_widget_show (priv->cc_caption);
1172 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1173 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1174 gtk_widget_hide (priv->cc_caption);
1177 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1178 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1179 gtk_widget_show (priv->bcc_caption);
1180 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1181 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1182 gtk_widget_hide (priv->bcc_caption);
1185 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1186 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1189 update_window_title (self);
1191 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1192 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1194 if ((body == NULL)||(body[0] == '\0')) {
1196 body = modest_text_utils_convert_to_html ("");
1199 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1200 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1203 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1206 /* Add attachments to the view */
1207 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1208 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1209 if (tny_list_get_length (priv->attachments) == 0) {
1210 gtk_widget_hide (priv->attachments_caption);
1212 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1213 gtk_widget_show_all (priv->attachments_caption);
1215 get_related_images (self, msg);
1216 update_next_cid (self, priv->attachments);
1217 update_next_cid (self, priv->images);
1218 replace_with_images (self, priv->images);
1220 if (preserve_is_rich && !is_html) {
1221 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1222 /* We must do this here in order to reset the undo
1223 list, because otherwise this action could be
1225 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1226 /* Get the default format required from configuration */
1227 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1228 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1229 /* We must do this here in order to reset the undo
1230 list, because otherwise this action could be
1232 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1235 /* Set the default focus depending on having already a To: field or not */
1236 if ((!to)||(*to == '\0')) {
1237 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1239 gtk_widget_grab_focus (priv->msg_body);
1242 /* TODO: lower priority, select in the From: combo to the
1243 value that comes from msg <- not sure, should it be
1246 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1248 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1249 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1251 modest_msg_edit_window_set_modified (self, FALSE);
1253 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1254 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1255 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1256 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1258 if (priv->msg_uid) {
1259 g_free (priv->msg_uid);
1260 priv->msg_uid = NULL;
1263 /* we should set a reference to the incoming message if it is a draft */
1264 msg_folder = tny_msg_get_folder (msg);
1266 if (modest_tny_folder_is_local_folder (msg_folder)) {
1267 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1268 if (type == TNY_FOLDER_TYPE_INVALID)
1269 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1271 if (type == TNY_FOLDER_TYPE_DRAFTS)
1272 priv->draft_msg = g_object_ref(msg);
1273 if (type == TNY_FOLDER_TYPE_OUTBOX)
1274 priv->outbox_msg = g_object_ref(msg);
1275 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1277 g_object_unref (msg_folder);
1287 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1290 GList *item_children, *node;
1291 GtkWidget *bin_child;
1293 bin_child = gtk_bin_get_child (GTK_BIN(item));
1295 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1297 for (node = item_children; node != NULL; node = g_list_next (node)) {
1298 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1299 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1302 g_list_free (item_children);
1306 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1309 GList *item_children, *node;
1311 box = gtk_bin_get_child (GTK_BIN (item));
1312 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1313 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1315 for (node = item_children; node != NULL; node = g_list_next (node)) {
1316 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1317 if (GTK_IS_TOGGLE_BUTTON (node->data))
1318 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1319 else if (GTK_IS_BUTTON (node->data))
1320 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1322 g_list_free (item_children);
1327 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1329 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1330 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1331 GtkWidget *placeholder;
1332 GtkWidget *tool_item;
1337 GtkWidget *sizes_menu;
1338 GtkWidget *fonts_menu;
1339 GSList *radio_group = NULL;
1340 GSList *node = NULL;
1344 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1345 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1347 /* Font color placeholder */
1348 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1349 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1352 tool_item = GTK_WIDGET (gtk_tool_item_new ());
1353 priv->font_color_button = hildon_color_button_new ();
1354 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1355 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1356 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
1357 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1358 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1359 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1360 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1362 G_CALLBACK (modest_msg_edit_window_color_button_change),
1365 /* Font size and face placeholder */
1366 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1367 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1369 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1370 priv->size_tool_button_label = gtk_label_new (NULL);
1371 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1372 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1373 size_text,"</span>", NULL);
1374 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1376 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1377 sizes_menu = gtk_menu_new ();
1378 priv->size_items_group = NULL;
1380 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1381 GtkWidget *size_menu_item;
1383 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1384 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1385 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1386 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1387 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1388 gtk_widget_show (size_menu_item);
1390 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1394 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1395 GtkWidget *item = (GtkWidget *) node->data;
1396 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1400 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1401 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1402 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1403 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1404 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1405 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1406 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1407 priv->font_size_toolitem = tool_item;
1410 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1411 priv->font_tool_button_label = gtk_label_new (NULL);
1412 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1413 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1415 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1416 fonts_menu = gtk_menu_new ();
1417 priv->font_items_group = NULL;
1419 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1420 GtkWidget *font_menu_item;
1421 GtkWidget *child_label;
1423 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1424 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1425 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1426 wp_get_font_name (font_index), "</span>", NULL);
1427 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1430 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1431 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1432 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1433 gtk_widget_show (font_menu_item);
1435 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1438 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1439 GtkWidget *item = (GtkWidget *) node->data;
1440 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1443 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1444 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1445 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1446 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1447 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1448 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1449 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1450 priv->font_face_toolitem = tool_item;
1452 /* Set expand and homogeneous for remaining items */
1453 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1454 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1455 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1456 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1457 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1458 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1459 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1460 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1461 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1463 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1464 will not show the tool items added to the placeholders) */
1465 gtk_widget_show_all (parent_priv->toolbar);
1467 /* Set the no show all *after* showing all items. We do not
1468 want the toolbar to be shown with a show all because it
1469 could go agains the gconf setting regarding showing or not
1470 the toolbar of the editor window */
1471 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1477 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1480 ModestWindowPrivate *parent_priv;
1481 ModestMsgEditWindowPrivate *priv;
1482 ModestDimmingRulesGroup *menu_rules_group = NULL;
1483 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1484 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1485 ModestWindowMgr *mgr = NULL;
1487 g_return_val_if_fail (msg, NULL);
1488 g_return_val_if_fail (account_name, NULL);
1490 mgr = modest_runtime_get_window_mgr ();
1492 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1494 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1495 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1497 /* Menubar. Update the state of some toggles */
1498 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1499 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1500 priv->from_field_protos = get_transports ();
1501 modest_combo_box_set_pair_list (MODEST_COMBO_BOX (priv->from_field), priv->from_field_protos);
1502 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), (gpointer) account_name);
1503 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1504 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1507 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1509 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1511 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1513 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1515 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1516 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1517 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1518 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1519 /* Add common dimming rules */
1520 modest_dimming_rules_group_add_rules (menu_rules_group,
1521 modest_msg_edit_window_menu_dimming_entries,
1522 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1523 MODEST_WINDOW (obj));
1524 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1525 modest_msg_edit_window_toolbar_dimming_entries,
1526 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1527 MODEST_WINDOW (obj));
1528 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1529 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1530 MODEST_WINDOW (obj));
1531 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
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_face_toolitem,
1535 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1536 MODEST_WINDOW (obj));
1537 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1538 modest_msg_edit_window_clipboard_dimming_entries,
1539 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1540 MODEST_WINDOW (obj));
1541 /* Insert dimming rules group for this window */
1542 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1543 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1544 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1545 /* Checks the dimming rules */
1546 g_object_unref (menu_rules_group);
1547 g_object_unref (toolbar_rules_group);
1548 g_object_unref (clipboard_rules_group);
1549 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1551 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1553 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1554 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1555 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1556 priv->update_caption_visibility = TRUE;
1558 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1560 /* Track account-removed signal, this window should be closed
1561 in the case we're creating a mail associated to the account
1563 priv->account_removed_handler_id =
1564 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1566 G_CALLBACK(on_account_removed),
1569 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1571 return (ModestWindow*) obj;
1575 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1577 GString **string_buffer = (GString **) user_data;
1579 *string_buffer = g_string_append (*string_buffer, buffer);
1585 * @result: A new string which should be freed with g_free().
1588 get_formatted_data (ModestMsgEditWindow *edit_window)
1590 ModestMsgEditWindowPrivate *priv;
1591 GString *string_buffer = g_string_new ("");
1593 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1595 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1597 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1599 return g_string_free (string_buffer, FALSE);
1604 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1607 const gchar *account_name;
1608 ModestMsgEditWindowPrivate *priv;
1609 TnyIterator *att_iter;
1611 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1613 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1615 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1616 g_return_val_if_fail (account_name, NULL);
1619 /* don't free these (except from) */
1620 data = g_slice_new0 (MsgData);
1621 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1623 data->account_name = g_strdup (account_name);
1624 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1625 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1626 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1627 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1628 if (priv->draft_msg) {
1629 data->draft_msg = g_object_ref (priv->draft_msg);
1630 } else if (priv->outbox_msg) {
1631 data->draft_msg = g_object_ref (priv->outbox_msg);
1633 data->draft_msg = NULL;
1636 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1638 gtk_text_buffer_get_bounds (buf, &b, &e);
1639 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1641 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1642 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1644 data->html_body = NULL;
1646 /* deep-copy the data */
1647 att_iter = tny_list_create_iterator (priv->attachments);
1648 data->attachments = NULL;
1649 while (!tny_iterator_is_done (att_iter)) {
1650 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1651 if (!(TNY_IS_MIME_PART(part))) {
1652 g_warning ("strange data in attachment list");
1653 g_object_unref (part);
1654 tny_iterator_next (att_iter);
1657 data->attachments = g_list_append (data->attachments,
1659 tny_iterator_next (att_iter);
1661 g_object_unref (att_iter);
1663 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1664 att_iter = tny_list_create_iterator (priv->images);
1665 data->images = NULL;
1666 while (!tny_iterator_is_done (att_iter)) {
1667 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1669 if (!(TNY_IS_MIME_PART(part))) {
1670 g_warning ("strange data in attachment list");
1671 g_object_unref (part);
1672 tny_iterator_next (att_iter);
1675 cid = tny_mime_part_get_content_id (part);
1677 gchar *image_tag_id;
1678 GtkTextTag *image_tag;
1680 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1681 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1682 g_free (image_tag_id);
1684 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1686 ((gtk_text_iter_has_tag (&iter, image_tag))||
1687 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1688 data->images = g_list_append (data->images,
1689 g_object_ref (part));
1691 g_object_unref (part);
1692 tny_iterator_next (att_iter);
1694 g_object_unref (att_iter);
1696 data->priority_flags = priv->priority_flags;
1703 unref_gobject (GObject *obj, gpointer data)
1705 if (!G_IS_OBJECT(obj))
1707 g_object_unref (obj);
1711 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1714 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1722 g_free (data->from);
1723 g_free (data->subject);
1724 g_free (data->plain_body);
1725 g_free (data->html_body);
1726 g_free (data->account_name);
1728 if (data->draft_msg != NULL) {
1729 g_object_unref (data->draft_msg);
1730 data->draft_msg = NULL;
1733 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1734 g_list_free (data->attachments);
1735 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1736 g_list_free (data->images);
1738 g_slice_free (MsgData, data);
1742 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1744 guint64 *parts_size)
1746 ModestMsgEditWindowPrivate *priv;
1748 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1750 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1752 /* TODO: add images */
1753 *parts_size += priv->images_size;
1754 *parts_count += priv->images_count;
1759 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1762 ModestMsgEditWindowPrivate *priv = NULL;
1763 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1765 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1767 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1769 return MODEST_MSG_EDIT_FORMAT_HTML;
1771 return MODEST_MSG_EDIT_FORMAT_TEXT;
1775 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1776 ModestMsgEditFormat format)
1778 ModestMsgEditWindowPrivate *priv;
1780 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1781 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1784 case MODEST_MSG_EDIT_FORMAT_HTML:
1785 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1787 case MODEST_MSG_EDIT_FORMAT_TEXT:
1788 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1791 g_return_if_reached ();
1795 ModestMsgEditFormatState *
1796 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1798 ModestMsgEditFormatState *format_state = NULL;
1799 ModestMsgEditWindowPrivate *priv;
1800 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1802 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1803 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1805 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1807 format_state = g_new0 (ModestMsgEditFormatState, 1);
1808 format_state->bold = buffer_format->bold&0x1;
1809 format_state->italics = buffer_format->italic&0x1;
1810 format_state->bullet = buffer_format->bullet&0x1;
1811 format_state->color = buffer_format->color;
1812 format_state->font_size = buffer_format->font_size;
1813 format_state->font_family = wp_get_font_name (buffer_format->font);
1814 format_state->justification = buffer_format->justification;
1815 g_free (buffer_format);
1817 return format_state;
1822 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1823 const ModestMsgEditFormatState *format_state)
1825 ModestMsgEditWindowPrivate *priv;
1826 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1827 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1828 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1829 g_return_if_fail (format_state != NULL);
1831 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1832 gtk_widget_grab_focus (priv->msg_body);
1833 buffer_format->bold = (format_state->bold != FALSE);
1834 buffer_format->italic = (format_state->italics != FALSE);
1835 buffer_format->color = format_state->color;
1836 buffer_format->font_size = format_state->font_size;
1837 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1838 buffer_format->justification = format_state->justification;
1839 buffer_format->bullet = format_state->bullet;
1841 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1843 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1844 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1845 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1846 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1847 buffer_format->cs.font = (buffer_format->font != current_format->font);
1848 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1849 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1851 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1852 if (buffer_format->cs.bold) {
1853 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1854 GINT_TO_POINTER (buffer_format->bold&0x1));
1856 if (buffer_format->cs.italic) {
1857 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1858 GINT_TO_POINTER (buffer_format->italic&0x1));
1860 if (buffer_format->cs.color) {
1861 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1862 GINT_TO_POINTER (&(buffer_format->color)));
1864 if (buffer_format->cs.font_size) {
1865 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1866 GINT_TO_POINTER (buffer_format->font_size));
1868 if (buffer_format->cs.justification) {
1869 switch (buffer_format->justification) {
1870 case GTK_JUSTIFY_LEFT:
1871 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1872 GINT_TO_POINTER(TRUE));
1874 case GTK_JUSTIFY_CENTER:
1875 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1876 GINT_TO_POINTER(TRUE));
1878 case GTK_JUSTIFY_RIGHT:
1879 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1880 GINT_TO_POINTER(TRUE));
1887 if (buffer_format->cs.font) {
1888 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1889 GINT_TO_POINTER (buffer_format->font));
1891 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1892 if (buffer_format->cs.bullet) {
1893 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1894 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1896 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1898 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1900 g_free (current_format);
1905 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1907 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1909 ModestWindowPrivate *parent_priv;
1910 ModestMsgEditWindowPrivate *priv;
1911 GtkWidget *new_size_menuitem;
1912 GtkWidget *new_font_menuitem;
1914 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1915 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1917 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1918 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1919 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1920 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1922 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1923 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1924 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1927 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1929 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1930 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1932 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1933 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1935 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1936 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1939 switch (buffer_format->justification)
1941 case GTK_JUSTIFY_LEFT:
1942 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1944 case GTK_JUSTIFY_CENTER:
1945 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1947 case GTK_JUSTIFY_RIGHT:
1948 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1955 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1957 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1958 G_CALLBACK (modest_msg_edit_window_color_button_change),
1960 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1961 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1962 G_CALLBACK (modest_msg_edit_window_color_button_change),
1965 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1966 buffer_format->font_size))->data);
1967 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1971 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1972 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1973 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1975 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1976 G_CALLBACK (modest_msg_edit_window_size_change),
1978 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1979 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1980 G_CALLBACK (modest_msg_edit_window_size_change),
1984 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1985 buffer_format->font))->data);
1986 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1990 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1991 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1992 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1994 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1995 G_CALLBACK (modest_msg_edit_window_font_change),
1997 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1998 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1999 G_CALLBACK (modest_msg_edit_window_font_change),
2003 g_free (buffer_format);
2007 #ifdef MODEST_HILDON_VERSION_0
2009 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2012 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2013 ModestMsgEditWindowPrivate *priv;
2014 GtkWidget *dialog = NULL;
2016 GdkColor *new_color = NULL;
2018 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2019 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2021 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2022 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2023 g_free (buffer_format);
2025 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2026 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2027 if (new_color != NULL) {
2028 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2029 (gpointer) new_color);
2032 gtk_widget_destroy (dialog);
2037 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2040 ModestMsgEditWindowPrivate *priv;
2041 GtkWidget *dialog = NULL;
2043 GdkColor *old_color = NULL;
2044 const GdkColor *new_color = NULL;
2046 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2047 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2049 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2050 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2052 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2053 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2054 if (new_color != NULL)
2055 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2057 gtk_widget_destroy (dialog);
2063 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2066 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2067 ModestMsgEditWindowPrivate *priv;
2068 GtkWidget *dialog = NULL;
2070 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2071 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2073 dialog = hildon_color_chooser_new ();
2074 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2075 g_free (buffer_format);
2077 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2079 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2080 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2083 gtk_widget_destroy (dialog);
2088 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2091 ModestMsgEditWindowPrivate *priv;
2092 GtkWidget *dialog = NULL;
2093 GdkColor *old_color = NULL;
2095 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2096 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2098 dialog = hildon_color_chooser_new ();
2099 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2101 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2103 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2104 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2106 gtk_widget_destroy (dialog);
2109 #endif /*!MODEST_HILDON_VERSION_0*/
2114 create_stream_for_uri (const gchar* uri)
2119 TnyStream *result = NULL;
2121 GnomeVFSHandle *handle = NULL;
2122 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2123 if (test == GNOME_VFS_OK) {
2124 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2125 /* Streams over OBEX (Bluetooth) are not seekable but
2126 * we expect them to be (we might need to read them
2127 * several times). So if this is a Bluetooth URI just
2128 * read the whole file into memory (this is not a fast
2129 * protocol so we can assume that these files are not
2130 * going to be very big) */
2131 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2132 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2133 TnyStream *memstream = tny_camel_mem_stream_new ();
2134 tny_stream_write_to_stream (vfssstream, memstream);
2135 g_object_unref (vfssstream);
2138 result = vfssstream;
2146 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2149 ModestMsgEditWindowPrivate *priv;
2150 GtkWidget *dialog = NULL;
2152 GSList *uris = NULL;
2153 GSList *uri_node = NULL;
2155 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2157 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2158 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2159 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2161 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2163 response = gtk_dialog_run (GTK_DIALOG (dialog));
2165 case GTK_RESPONSE_OK:
2166 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2171 gtk_widget_destroy (dialog);
2173 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2175 GnomeVFSHandle *handle = NULL;
2176 GnomeVFSResult result;
2177 GtkTextIter position;
2178 GtkTextMark *insert_mark;
2180 uri = (const gchar *) uri_node->data;
2181 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2182 if (result == GNOME_VFS_OK) {
2184 GnomeVFSFileInfo *info;
2185 gchar *filename, *basename, *escaped_filename;
2186 TnyMimePart *mime_part;
2188 const gchar *mime_type = NULL;
2189 GnomeVFSURI *vfs_uri;
2190 guint64 stream_size;
2192 gnome_vfs_close (handle);
2193 vfs_uri = gnome_vfs_uri_new (uri);
2195 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2196 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2197 g_free (escaped_filename);
2198 gnome_vfs_uri_unref (vfs_uri);
2199 info = gnome_vfs_file_info_new ();
2201 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2202 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2204 mime_type = gnome_vfs_file_info_get_mime_type (info);
2206 mime_part = tny_platform_factory_new_mime_part
2207 (modest_runtime_get_platform_factory ());
2209 TnyStream *stream = create_stream_for_uri (uri);
2211 if (stream == NULL) {
2213 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2215 g_object_unref (mime_part);
2216 gnome_vfs_file_info_unref (info);
2220 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2222 content_id = g_strdup_printf ("%d", priv->next_cid);
2223 tny_mime_part_set_content_id (mime_part, content_id);
2224 g_free (content_id);
2227 basename = g_path_get_basename (filename);
2228 tny_mime_part_set_filename (mime_part, basename);
2231 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2233 if (pixbuf != NULL) {
2234 priv->images_size += stream_size;
2235 priv->images_count ++;
2236 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2237 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2238 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2241 tny_list_prepend (priv->images, (GObject *) mime_part);
2242 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2244 g_object_unref (mime_part);
2245 gnome_vfs_file_info_unref (info);
2254 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2256 GtkWidget *dialog = NULL;
2258 GSList *uris = NULL;
2260 GnomeVFSFileSize total_size, allowed_size;
2261 ModestMsgEditWindowPrivate *priv;
2265 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2267 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2269 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2272 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2273 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2274 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2275 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
2277 response = gtk_dialog_run (GTK_DIALOG (dialog));
2279 case GTK_RESPONSE_OK:
2280 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2285 gtk_widget_destroy (dialog);
2287 /* allowed size is the maximum size - what's already there */
2288 modest_attachments_view_get_sizes (
2289 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2290 &att_num, &att_size);
2291 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2294 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2296 const gchar *uri = (const gchar *) uri_node->data;
2298 total_size += modest_msg_edit_window_attach_file_one
2299 (window, uri, allowed_size);
2301 if (total_size > allowed_size) {
2302 g_warning ("%s: total size: %u",
2303 __FUNCTION__, (unsigned int)total_size);
2307 allowed_size -= total_size;
2311 g_slist_foreach (uris, (GFunc) g_free, NULL);
2312 g_slist_free (uris);
2317 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2319 GnomeVFSFileSize allowed_size)
2322 GnomeVFSHandle *handle = NULL;
2323 ModestMsgEditWindowPrivate *priv;
2324 GnomeVFSResult result;
2325 GnomeVFSFileSize size = 0;
2327 g_return_val_if_fail (window, 0);
2328 g_return_val_if_fail (uri, 0);
2330 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2332 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2333 if (result == GNOME_VFS_OK) {
2334 TnyMimePart *mime_part;
2336 const gchar *mime_type = NULL;
2338 gchar *escaped_filename;
2341 GnomeVFSFileInfo *info;
2342 GnomeVFSURI *vfs_uri;
2344 gnome_vfs_close (handle);
2345 vfs_uri = gnome_vfs_uri_new (uri);
2348 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2349 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2350 g_free (escaped_filename);
2351 gnome_vfs_uri_unref (vfs_uri);
2353 info = gnome_vfs_file_info_new ();
2355 if (gnome_vfs_get_file_info (uri,
2357 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2359 mime_type = gnome_vfs_file_info_get_mime_type (info);
2360 mime_part = tny_platform_factory_new_mime_part
2361 (modest_runtime_get_platform_factory ());
2363 /* try to get the attachment's size; this may fail for weird
2364 * file systems, like obex, upnp... */
2365 if (allowed_size != 0 &&
2366 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2368 if (size > allowed_size) {
2369 g_warning ("%s: attachment too big", __FUNCTION__);
2370 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2374 g_warning ("%s: could not get attachment size", __FUNCTION__);
2376 stream = create_stream_for_uri (uri);
2378 if (stream == NULL) {
2380 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2382 g_object_unref (mime_part);
2383 gnome_vfs_file_info_unref (info);
2387 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2388 g_object_unref (stream);
2390 content_id = g_strdup_printf ("%d", priv->next_cid);
2391 tny_mime_part_set_content_id (mime_part, content_id);
2392 g_free (content_id);
2395 basename = g_path_get_basename (filename);
2396 tny_mime_part_set_filename (mime_part, basename);
2399 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2400 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2402 info->size == 0, info->size);
2403 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2404 gtk_widget_show_all (priv->attachments_caption);
2405 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2407 g_object_unref (mime_part);
2408 gnome_vfs_file_info_unref (info);
2415 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2418 ModestMsgEditWindowPrivate *priv;
2421 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2422 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2424 if (att_list == NULL) {
2425 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2427 g_object_ref (att_list);
2430 if (tny_list_get_length (att_list) == 0) {
2431 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2433 GtkWidget *confirmation_dialog = NULL;
2434 gboolean dialog_response;
2435 gchar *message = NULL;
2436 gchar *filename = NULL;
2438 if (tny_list_get_length (att_list) == 1) {
2440 iter = tny_list_create_iterator (att_list);
2441 part = (TnyMimePart *) tny_iterator_get_current (iter);
2442 g_object_unref (iter);
2443 if (TNY_IS_MSG (part)) {
2444 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2446 filename = tny_header_dup_subject (header);
2447 g_object_unref (header);
2449 if (filename == NULL) {
2450 filename = g_strdup (_("mail_va_no_subject"));
2453 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2455 g_object_unref (part);
2457 filename = g_strdup ("");
2459 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2460 tny_list_get_length (att_list)), filename);
2462 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
2464 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
2465 gtk_widget_destroy (confirmation_dialog);
2466 if (!dialog_response) {
2467 g_object_unref (att_list);
2470 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
2472 for (iter = tny_list_create_iterator (att_list);
2473 !tny_iterator_is_done (iter);
2474 tny_iterator_next (iter)) {
2475 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2476 const gchar *att_id;
2477 tny_list_remove (priv->attachments, (GObject *) mime_part);
2479 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2481 if (tny_list_get_length (priv->attachments) == 0)
2482 gtk_widget_hide (priv->attachments_caption);
2483 att_id = tny_mime_part_get_content_id (mime_part);
2485 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2487 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2488 g_object_unref (mime_part);
2490 g_object_unref (iter);
2493 g_object_unref (att_list);
2495 /* if the last attachment has been removed, focus the Subject: field */
2496 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2497 gtk_widget_grab_focus (priv->subject_field);
2501 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2504 ModestMsgEditWindowPrivate *priv;
2505 GdkColor *new_color;
2506 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2508 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2509 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2512 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2514 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2516 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2518 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2523 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2526 ModestMsgEditWindowPrivate *priv;
2527 gint new_size_index;
2528 ModestMsgEditWindow *window;
2531 window = MODEST_MSG_EDIT_WINDOW (userdata);
2532 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2533 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2535 if (gtk_check_menu_item_get_active (menu_item)) {
2537 WPTextBufferFormat format;
2539 memset (&format, 0, sizeof (format));
2540 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2542 label = gtk_bin_get_child (GTK_BIN (menu_item));
2544 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2545 format.cs.font_size = TRUE;
2546 format.cs.text_position = TRUE;
2547 format.cs.font = TRUE;
2548 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2549 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2551 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2552 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2553 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2555 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2556 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2557 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2563 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2566 ModestMsgEditWindowPrivate *priv;
2567 gint new_font_index;
2568 ModestMsgEditWindow *window;
2571 window = MODEST_MSG_EDIT_WINDOW (userdata);
2572 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2573 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2575 if (gtk_check_menu_item_get_active (menu_item)) {
2578 label = gtk_bin_get_child (GTK_BIN (menu_item));
2580 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2582 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2583 GINT_TO_POINTER(new_font_index)))
2584 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2586 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2587 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2588 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2594 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2596 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2597 ModestWindowPrivate *parent_priv;
2598 ModestWindowMgr *mgr;
2599 gboolean is_fullscreen;
2600 GtkAction *fs_toggle_action;
2603 mgr = modest_runtime_get_window_mgr ();
2604 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2606 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2608 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2609 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2610 if (is_fullscreen != active)
2611 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2619 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2622 ModestMsgEditWindowPrivate *priv = NULL;
2623 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2625 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2626 if (!priv->update_caption_visibility)
2629 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2631 gtk_widget_show (priv->cc_caption);
2633 gtk_widget_hide (priv->cc_caption);
2635 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2639 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2642 ModestMsgEditWindowPrivate *priv = NULL;
2643 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2645 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2646 if (!priv->update_caption_visibility)
2649 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2651 gtk_widget_show (priv->bcc_caption);
2653 gtk_widget_hide (priv->bcc_caption);
2655 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2659 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2660 ModestRecptEditor *editor)
2662 ModestMsgEditWindowPrivate *priv;
2664 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2665 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2667 /* we check for low-mem; in that case, show a warning, and don't allow
2668 * for the addressbook
2670 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2673 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2675 if (editor == NULL) {
2676 GtkWidget *view_focus;
2677 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2679 /* This code should be kept in sync with ModestRecptEditor. The
2680 textview inside the recpt editor is the one that really gets the
2681 focus. As it's inside a scrolled window, and this one inside the
2682 hbox recpt editor inherits from, we'll need to go up in the
2683 hierarchy to know if the text view is part of the recpt editor
2684 or if it's a different text entry */
2686 if (gtk_widget_get_parent (view_focus)) {
2687 GtkWidget *first_parent;
2689 first_parent = gtk_widget_get_parent (view_focus);
2690 if (gtk_widget_get_parent (first_parent) &&
2691 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2692 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2697 editor = MODEST_RECPT_EDITOR (priv->to_field);
2701 modest_address_book_select_addresses (editor);
2706 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2708 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2710 modest_msg_edit_window_open_addressbook (window, NULL);
2714 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2715 gboolean show_toolbar)
2717 ModestWindowPrivate *parent_priv;
2718 const gchar *action_name;
2721 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2722 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2724 /* We can not just use the code of
2725 modest_msg_edit_window_setup_toolbar because it has a
2726 mixture of both initialization and creation code. */
2728 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2730 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2732 /* Update also the actions (to update the toggles in the
2733 menus), we have to do it manually because some other window
2734 of the same time could have changed it (remember that the
2735 toolbar fullscreen mode is shared by all the windows of the
2737 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2738 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2740 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2742 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2743 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2749 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2750 TnyHeaderFlags priority_flags)
2752 ModestMsgEditWindowPrivate *priv;
2753 ModestWindowPrivate *parent_priv;
2755 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2757 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2758 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2760 if (priv->priority_flags != priority_flags) {
2761 GtkAction *priority_action = NULL;
2763 priv->priority_flags = priority_flags;
2765 switch (priority_flags) {
2766 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2767 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2768 gtk_widget_show (priv->priority_icon);
2769 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2770 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2772 case TNY_HEADER_FLAG_LOW_PRIORITY:
2773 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2774 gtk_widget_show (priv->priority_icon);
2775 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2776 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2779 gtk_widget_hide (priv->priority_icon);
2780 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2781 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2784 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2785 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2790 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2793 ModestMsgEditWindowPrivate *priv;
2794 ModestWindowPrivate *parent_priv;
2795 gint current_format;
2797 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2799 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2800 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2802 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2803 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2805 if (current_format != file_format) {
2806 switch (file_format) {
2807 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2808 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2809 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2811 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2815 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2816 response = gtk_dialog_run (GTK_DIALOG (dialog));
2817 gtk_widget_destroy (dialog);
2818 if (response == GTK_RESPONSE_OK) {
2819 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2821 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2822 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2827 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2828 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2833 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2836 ModestMsgEditWindowPrivate *priv;
2837 WPTextBufferFormat oldfmt, fmt;
2838 gint old_position = 0;
2842 GdkColor *color = NULL;
2843 gboolean bold, bold_set, italic, italic_set;
2844 gboolean underline, underline_set;
2845 gboolean strikethrough, strikethrough_set;
2846 gboolean position_set;
2847 gboolean font_size_set, font_set, color_set;
2850 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2851 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2853 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2854 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2855 GTK_WINDOW(dialog));
2857 /* First we get the currently selected font information */
2858 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2860 switch (oldfmt.text_position) {
2861 case TEXT_POSITION_NORMAL:
2864 case TEXT_POSITION_SUPERSCRIPT:
2872 g_object_set (G_OBJECT (dialog),
2873 "bold", oldfmt.bold != FALSE,
2874 "bold-set", !oldfmt.cs.bold,
2875 "underline", oldfmt.underline != FALSE,
2876 "underline-set", !oldfmt.cs.underline,
2877 "italic", oldfmt.italic != FALSE,
2878 "italic-set", !oldfmt.cs.italic,
2879 "strikethrough", oldfmt.strikethrough != FALSE,
2880 "strikethrough-set", !oldfmt.cs.strikethrough,
2881 "color", &oldfmt.color,
2882 "color-set", !oldfmt.cs.color,
2883 "size", wp_font_size[oldfmt.font_size],
2884 "size-set", !oldfmt.cs.font_size,
2885 "position", old_position,
2886 "position-set", !oldfmt.cs.text_position,
2887 "family", wp_get_font_name (oldfmt.font),
2888 "family-set", !oldfmt.cs.font,
2891 gtk_widget_show_all (dialog);
2892 priv->font_dialog = dialog;
2893 response = gtk_dialog_run (GTK_DIALOG (dialog));
2894 priv->font_dialog = NULL;
2895 if (response == GTK_RESPONSE_OK) {
2897 g_object_get( dialog,
2899 "bold-set", &bold_set,
2900 "underline", &underline,
2901 "underline-set", &underline_set,
2903 "italic-set", &italic_set,
2904 "strikethrough", &strikethrough,
2905 "strikethrough-set", &strikethrough_set,
2907 "color-set", &color_set,
2909 "size-set", &font_size_set,
2910 "family", &font_name,
2911 "family-set", &font_set,
2912 "position", &position,
2913 "position-set", &position_set,
2918 if (response == GTK_RESPONSE_OK) {
2919 memset(&fmt, 0, sizeof(fmt));
2925 fmt.italic = italic;
2926 fmt.cs.italic = TRUE;
2928 if (underline_set) {
2929 fmt.underline = underline;
2930 fmt.cs.underline = TRUE;
2932 if (strikethrough_set) {
2933 fmt.strikethrough = strikethrough;
2934 fmt.cs.strikethrough = TRUE;
2939 ? TEXT_POSITION_NORMAL
2940 : ( ( position == 1 )
2941 ? TEXT_POSITION_SUPERSCRIPT
2942 : TEXT_POSITION_SUBSCRIPT );
2943 fmt.cs.text_position = TRUE;
2944 fmt.font_size = oldfmt.font_size;
2948 fmt.cs.color = TRUE;
2951 fmt.font = wp_get_font_index(font_name,
2956 if (font_size_set) {
2957 fmt.cs.font_size = TRUE;
2958 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2960 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2961 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2963 gtk_widget_destroy (dialog);
2965 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2969 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2971 ModestMsgEditWindowPrivate *priv;
2973 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2974 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2976 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2978 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2979 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2984 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2986 ModestMsgEditWindowPrivate *priv;
2988 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2989 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2991 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2993 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2994 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2999 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3001 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3003 priv->can_undo = can_undo;
3007 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3009 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3011 priv->can_redo = can_redo;
3015 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3017 ModestMsgEditWindowPrivate *priv;
3018 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3019 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3021 return priv->can_undo;
3025 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3027 ModestMsgEditWindowPrivate *priv;
3028 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3029 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3031 return priv->can_redo;
3036 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3039 GtkTextIter match_start, match_end;
3041 if (image_id == NULL)
3044 gtk_text_buffer_get_start_iter (buffer, &iter);
3046 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3047 GSList *tags = gtk_text_iter_get_tags (&match_start);
3049 for (node = tags; node != NULL; node = g_slist_next (node)) {
3050 GtkTextTag *tag = (GtkTextTag *) node->data;
3051 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3052 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3053 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3055 offset = gtk_text_iter_get_offset (&match_start);
3056 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3057 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3061 gtk_text_iter_forward_char (&iter);
3066 message_is_empty (ModestMsgEditWindow *window)
3068 ModestMsgEditWindowPrivate *priv = NULL;
3070 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3071 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3073 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3074 * so we can ignore markup.
3076 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3079 count = gtk_text_buffer_get_char_count (buf);
3085 msg_body_focus (GtkWidget *focus,
3086 GdkEventFocus *event,
3090 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3091 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3092 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3097 recpt_field_changed (GtkTextBuffer *buffer,
3098 ModestMsgEditWindow *editor)
3100 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3101 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3105 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3107 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3108 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3112 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3115 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3116 GtkTextBuffer *buffer;
3118 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3119 gtk_text_buffer_set_modified (buffer, modified);
3120 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3121 gtk_text_buffer_set_modified (buffer, modified);
3122 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3123 gtk_text_buffer_set_modified (buffer, modified);
3124 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3128 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3130 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3131 const char *account_name;
3132 GtkTextBuffer *buffer;
3134 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3135 if (gtk_text_buffer_get_modified (buffer))
3137 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3138 if (gtk_text_buffer_get_modified (buffer))
3140 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3141 if (gtk_text_buffer_get_modified (buffer))
3143 if (gtk_text_buffer_get_modified (priv->text_buffer))
3145 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
3146 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3157 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3159 ModestMsgEditWindowPrivate *priv = NULL;
3161 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3162 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3164 /* check if there's no recipient added */
3165 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3166 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3167 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3168 /* no recipient contents, then select contacts */
3169 modest_msg_edit_window_open_addressbook (window, NULL);
3173 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3174 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3177 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3178 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3181 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3182 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3186 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3187 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3188 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3195 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3196 ModestMsgEditWindow *window)
3198 modest_msg_edit_window_offer_attach_file (window);
3202 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3204 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3206 return priv->clipboard_text;
3210 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3212 ModestMsgEditWindow *window)
3214 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3215 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3217 if (!GTK_WIDGET_VISIBLE (window))
3220 g_object_ref (window);
3221 text = gtk_clipboard_wait_for_text (selection_clipboard);
3223 if (priv->clipboard_text != NULL) {
3224 g_free (priv->clipboard_text);
3226 priv->clipboard_text = text;
3228 if (GTK_WIDGET_VISIBLE (window)) {
3229 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3231 g_object_unref (window);
3234 static gboolean clipboard_owner_change_idle (gpointer userdata)
3236 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3237 ModestMsgEditWindowPrivate *priv;
3239 gdk_threads_enter ();
3240 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3241 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3243 priv->clipboard_owner_idle = 0;
3244 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3245 gdk_threads_leave ();
3251 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3253 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3254 if (priv->clipboard_owner_idle == 0) {
3255 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3260 subject_field_move_cursor (GtkEntry *entry,
3261 GtkMovementStep step,
3266 if (!GTK_WIDGET_VISIBLE (window))
3269 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3273 update_window_title (ModestMsgEditWindow *window)
3275 ModestMsgEditWindowPrivate *priv = NULL;
3276 const gchar *subject;
3278 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3279 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3280 if (subject == NULL || subject[0] == '\0')
3281 subject = _("mail_va_new_email");
3283 gtk_window_set_title (GTK_WINDOW (window), subject);
3288 subject_field_changed (GtkEditable *editable,
3289 ModestMsgEditWindow *window)
3291 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3292 update_window_title (window);
3293 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3294 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3295 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3299 subject_field_insert_text (GtkEditable *editable,
3301 gint new_text_length,
3303 ModestMsgEditWindow *window)
3305 GString *result = g_string_new ("");
3307 gint result_len = 0;
3308 const gchar *entry_text = NULL;
3311 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3312 old_length = g_utf8_strlen (entry_text, -1);
3314 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3315 gunichar c = g_utf8_get_char_validated (current, 8);
3316 /* Invalid unichar, stop */
3322 result = g_string_append_unichar (result, c);
3326 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3327 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3330 /* Prevent endless recursion */
3331 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3332 g_signal_emit_by_name (editable, "insert-text",
3333 (gpointer) result->str, (gpointer) result->len,
3334 (gpointer) position, (gpointer) window);
3335 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3339 if (result_len + old_length > 1000) {
3340 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3341 dgettext("hildon-common-strings",
3342 "ckdg_ib_maximum_characters_reached"));
3345 g_string_free (result, TRUE);
3349 text_buffer_insert_text (GtkTextBuffer *buffer,
3352 gint new_text_length,
3353 ModestMsgEditWindow *window)
3355 GString *result = g_string_new ("");
3357 gint result_len = 0;
3358 gboolean changed = FALSE;
3360 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3361 gunichar c = g_utf8_get_char_validated (current, 8);
3362 /* Invalid unichar, stop */
3368 result = g_string_append_c (result, ' ');
3372 result = g_string_append_unichar (result, c);
3378 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3379 g_signal_handlers_block_by_func(G_OBJECT(buffer), G_CALLBACK(text_buffer_insert_text), window);
3380 g_signal_emit_by_name (buffer, "insert-text",
3382 (gpointer) result->str, (gpointer) result->len,
3384 g_signal_handlers_unblock_by_func(G_OBJECT(buffer), G_CALLBACK(text_buffer_insert_text), window);
3387 g_string_free (result, TRUE);
3391 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3394 ModestMsgEditWindowPrivate *priv = NULL;
3396 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3397 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3399 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3402 gtk_widget_show_all (priv->find_toolbar);
3403 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3405 gtk_widget_hide_all (priv->find_toolbar);
3406 gtk_widget_grab_focus (priv->msg_body);
3412 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3414 GtkTextIter *match_start,
3415 GtkTextIter *match_end)
3417 GtkTextIter end_iter;
3418 gchar *str_casefold;
3421 gchar *range_casefold;
3424 gboolean result = FALSE;
3431 gtk_text_iter_forward_to_end (&end_iter);
3433 str_casefold = g_utf8_casefold (str, -1);
3434 str_chars_n = strlen (str);
3436 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3437 range_casefold = g_utf8_casefold (range_text, -1);
3438 range_chars_n = strlen (range_casefold);
3440 if (range_chars_n < str_chars_n) {
3441 g_free (str_casefold);
3442 g_free (range_text);
3443 g_free (range_casefold);
3447 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3448 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3449 if (!g_utf8_collate (range_subtext, str_casefold)) {
3450 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3452 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3453 match_start, match_end, NULL);
3454 g_free (found_text);
3456 g_free (range_subtext);
3460 g_free (str_casefold);
3461 g_free (range_text);
3462 g_free (range_casefold);
3469 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3470 ModestMsgEditWindow *window)
3472 gchar *current_search = NULL;
3473 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3475 GtkTextIter selection_start, selection_end;
3476 GtkTextIter match_start, match_end;
3477 gboolean continue_search = FALSE;
3479 if (message_is_empty (window)) {
3480 g_free (priv->last_search);
3481 priv->last_search = NULL;
3482 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3486 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3487 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3488 g_free (current_search);
3489 g_free (priv->last_search);
3490 priv->last_search = NULL;
3491 /* Information banner about empty search */
3492 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3496 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3497 continue_search = TRUE;
3499 g_free (priv->last_search);
3500 priv->last_search = g_strdup (current_search);
3503 if (continue_search) {
3504 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3505 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3506 &match_start, &match_end);
3508 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3510 GtkTextIter buffer_start;
3511 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3512 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3513 &match_start, &match_end);
3515 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3518 /* Mark as selected the string found in search */
3520 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3521 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3522 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3524 g_free (priv->last_search);
3525 priv->last_search = NULL;
3527 g_free (current_search);
3531 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3532 ModestMsgEditWindow *window)
3534 GtkToggleAction *toggle;
3535 ModestWindowPrivate *parent_priv;
3536 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3538 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3539 gtk_toggle_action_set_active (toggle, FALSE);
3543 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3545 ModestMsgEditWindowPrivate *priv;
3547 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3552 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3555 ModestMsgEditWindowPrivate *priv;
3557 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3563 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3566 ModestMsgEditWindowPrivate *priv;
3567 TnyHeader *header = NULL;
3569 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3570 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3572 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3573 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3575 if (priv->draft_msg != NULL) {
3576 g_object_unref (priv->draft_msg);
3579 if (draft != NULL) {
3580 g_object_ref (draft);
3581 header = tny_msg_get_header (draft);
3582 if (priv->msg_uid) {
3583 g_free (priv->msg_uid);
3584 priv->msg_uid = NULL;
3586 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3587 if (GTK_WIDGET_REALIZED (window))
3588 modest_window_mgr_register_window (mgr, MODEST_WINDOW (window));
3591 priv->draft_msg = draft;
3595 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3596 GtkTextIter *start, GtkTextIter *end,
3599 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3600 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3603 if (tag == NULL+13) return;
3604 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3605 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3606 replace_with_images (window, priv->images);
3611 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3614 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3616 g_return_if_fail (TNY_IS_MIME_PART (part));
3617 tny_list_prepend (priv->attachments, (GObject *) part);
3618 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3619 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3620 gtk_widget_show_all (priv->attachments_caption);
3621 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3625 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3627 ModestMsgEditWindowPrivate *priv;
3629 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3630 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3632 return priv->msg_uid;
3636 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3637 ModestMsgEditWindowWidgetType widget_type)
3639 ModestMsgEditWindowPrivate *priv;
3641 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3642 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3644 switch (widget_type) {
3645 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3646 return priv->msg_body;
3648 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3649 return priv->to_field;
3651 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3652 return priv->cc_field;
3654 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3655 return priv->bcc_field;
3657 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3658 return priv->subject_field;
3660 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3661 return priv->attachments_view;
3669 remove_tags (WPTextBuffer *buffer)
3671 GtkTextIter start, end;
3673 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3674 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3676 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3680 on_account_removed (TnyAccountStore *account_store,
3681 TnyAccount *account,
3684 /* Do nothing if it's a store account, because we use the
3685 transport to send the messages */
3686 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3687 const gchar *parent_acc = NULL;
3688 const gchar *our_acc = NULL;
3690 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3691 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3692 /* Close this window if I'm showing a message of the removed account */
3693 if (strcmp (parent_acc, our_acc) == 0)
3694 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3699 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3701 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3703 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3709 set_zoom_do_nothing (ModestWindow *window,
3715 get_zoom_do_nothing (ModestWindow *window)