1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
42 #include <modest-account-mgr.h>
43 #include <modest-account-mgr-helpers.h>
45 #include <widgets/modest-msg-edit-window.h>
46 #include <modest-selector-picker.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <wptextview.h>
65 #include <wptextbuffer.h>
66 #include <hildon/hildon-pannable-area.h>
67 #include "modest-msg-edit-window-ui-dimming.h"
69 #include "modest-hildon-includes.h"
70 #ifdef MODEST_HAVE_HILDON0_WIDGETS
71 #include <hildon-widgets/hildon-color-chooser.h>
73 #include "widgets/modest-msg-edit-window-ui.h"
74 #ifdef MODEST_HAVE_HILDON0_WIDGETS
75 #include <libgnomevfs/gnome-vfs-mime-utils.h>
77 #include <libgnomevfs/gnome-vfs-mime.h>
79 #include <modest-utils.h>
80 #include "modest-maemo-utils.h"
81 #include <modest-ui-constants.h>
84 #define DEFAULT_FONT_SIZE 3
85 #define DEFAULT_FONT 2
86 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
87 #define DEFAULT_MAIN_VBOX_SPACING 6
88 #define SUBJECT_MAX_LENGTH 1000
89 #define IMAGE_MAX_WIDTH 560
90 #define DEFAULT_FONT_SCALE 1.5
92 static gboolean is_wp_text_buffer_started = FALSE;
94 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
95 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
96 static void modest_msg_edit_window_finalize (GObject *obj);
98 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
99 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
100 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
102 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
103 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
104 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
105 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
106 GtkTextIter *start, GtkTextIter *end,
108 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
109 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
110 static void subject_field_insert_text (GtkEditable *editable,
112 gint new_text_length,
114 ModestMsgEditWindow *window);
115 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
117 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
119 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
121 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
122 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
123 GdkEventWindowState *event,
125 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
126 ModestRecptEditor *editor);
127 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
128 ModestMsgEditWindow *window);
130 /* ModestWindow methods implementation */
131 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
132 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
133 gboolean show_toolbar);
134 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
136 ModestMsgEditWindow *window);
137 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
138 static void subject_field_move_cursor (GtkEntry *entry,
139 GtkMovementStep step,
143 static void update_window_title (ModestMsgEditWindow *window);
146 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
147 ModestMsgEditWindow *window);
148 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
149 ModestMsgEditWindow *window);
150 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
152 GtkTextIter *match_start,
153 GtkTextIter *match_end);
155 static void remove_tags (WPTextBuffer *buffer);
157 static void on_account_removed (TnyAccountStore *account_store,
161 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
162 static void set_zoom_do_nothing (ModestWindow *window, gdouble zoom);
163 static gdouble get_zoom_do_nothing (ModestWindow *window);
165 static void init_window (ModestMsgEditWindow *obj);
167 gboolean scroll_drag_timeout (gpointer userdata);
168 static void correct_scroll (ModestMsgEditWindow *w);
169 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
170 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
171 ModestMsgEditWindow *userdata);
172 static void text_buffer_mark_set (GtkTextBuffer *buffer,
175 ModestMsgEditWindow *userdata);
177 static void DEBUG_BUFFER (WPTextBuffer *buffer)
181 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
183 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
184 while (!gtk_text_iter_is_end (&iter)) {
185 GString *output = g_string_new ("");
186 GSList *toggled_tags;
189 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
190 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
191 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
192 GtkTextTag *tag = (GtkTextTag *) node->data;
194 g_object_get (G_OBJECT (tag), "name", &name, NULL);
195 output = g_string_append (output, name);
196 g_string_append (output, " ");
198 output = g_string_append (output, "] OPENED [ ");
199 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
200 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
201 GtkTextTag *tag = (GtkTextTag *) node->data;
203 g_object_get (G_OBJECT (tag), "name", &name, NULL);
204 output = g_string_append (output, name);
205 g_string_append (output, " ");
207 output = g_string_append (output, "]\n");
208 g_message ("%s", output->str);
209 g_string_free (output, TRUE);
210 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
212 g_message ("END BUFFER");
217 /* static gboolean */
218 /* on_key_pressed (GtkWidget *self, */
219 /* GdkEventKey *event, */
220 /* gpointer user_data); */
222 /* list my signals */
229 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
230 struct _ModestMsgEditWindowPrivate {
233 GtkWidget *header_box;
235 ModestPairList *from_field_protos;
236 GtkWidget *from_field;
237 gchar *original_account_name;
241 GtkWidget *bcc_field;
242 GtkWidget *subject_field;
243 GtkWidget *attachments_view;
244 GtkWidget *priority_icon;
245 GtkWidget *add_attachment_button;
247 GtkWidget *cc_caption;
248 GtkWidget *bcc_caption;
249 gboolean update_caption_visibility;
250 GtkWidget *attachments_caption;
252 GtkTextBuffer *text_buffer;
254 GtkWidget *font_size_toolitem;
255 GtkWidget *font_face_toolitem;
256 GtkWidget *font_color_button;
257 GSList *font_items_group;
258 GtkWidget *font_tool_button_label;
259 GSList *size_items_group;
260 GtkWidget *size_tool_button_label;
262 GtkWidget *find_toolbar;
265 GtkWidget *font_dialog;
268 guint scroll_drag_timeout_id;
272 TnyList *attachments;
277 TnyHeaderFlags priority_flags;
279 gboolean can_undo, can_redo;
280 gulong clipboard_change_handler_id;
281 gulong default_clipboard_change_handler_id;
282 gulong account_removed_handler_id;
283 guint clipboard_owner_idle;
284 gchar *clipboard_text;
293 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
294 MODEST_TYPE_MSG_EDIT_WINDOW, \
295 ModestMsgEditWindowPrivate))
297 static GtkWindowClass *parent_class = NULL;
299 /* uncomment the following if you have defined any signals */
300 /* static guint signals[LAST_SIGNAL] = {0}; */
303 modest_msg_edit_window_get_type (void)
305 static GType my_type = 0;
307 static const GTypeInfo my_info = {
308 sizeof(ModestMsgEditWindowClass),
309 NULL, /* base init */
310 NULL, /* base finalize */
311 (GClassInitFunc) modest_msg_edit_window_class_init,
312 NULL, /* class finalize */
313 NULL, /* class data */
314 sizeof(ModestMsgEditWindow),
316 (GInstanceInitFunc) modest_msg_edit_window_init,
319 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
320 "ModestMsgEditWindow",
328 save_state (ModestWindow *self)
330 modest_widget_memory_save (modest_runtime_get_conf(),
331 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
336 restore_settings (ModestMsgEditWindow *self)
338 ModestConf *conf = NULL;
340 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
342 conf = modest_runtime_get_conf ();
343 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
344 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
345 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
346 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL));
347 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
348 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu");
349 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
350 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
352 /* set initial state of cc and bcc */
353 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
354 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
355 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
356 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
357 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
358 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
360 /* Dim at start clipboard actions */
361 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
362 gtk_action_set_sensitive (action, FALSE);
363 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
364 gtk_action_set_sensitive (action, FALSE);
365 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
366 gtk_action_set_sensitive (action, FALSE);
368 modest_widget_memory_restore (conf,
369 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
374 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
376 GObjectClass *gobject_class;
377 ModestWindowClass *modest_window_class;
378 gobject_class = (GObjectClass*) klass;
379 modest_window_class = (ModestWindowClass*) klass;
381 parent_class = g_type_class_peek_parent (klass);
382 gobject_class->finalize = modest_msg_edit_window_finalize;
384 modest_window_class->set_zoom_func = set_zoom_do_nothing;
385 modest_window_class->get_zoom_func = get_zoom_do_nothing;
386 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
387 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
388 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
389 modest_window_class->save_state_func = save_state;
390 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
392 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
396 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
398 ModestMsgEditWindowPrivate *priv;
399 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
401 priv->msg_body = NULL;
403 priv->from_field = NULL;
404 priv->to_field = NULL;
405 priv->cc_field = NULL;
406 priv->bcc_field = NULL;
407 priv->subject_field = NULL;
408 priv->attachments = TNY_LIST (tny_simple_list_new ());
409 priv->images = TNY_LIST (tny_simple_list_new ());
410 priv->images_size = 0;
411 priv->images_count = 0;
414 priv->cc_caption = NULL;
415 priv->bcc_caption = NULL;
416 priv->update_caption_visibility = FALSE;
418 priv->priority_flags = 0;
420 priv->find_toolbar = NULL;
421 priv->last_search = NULL;
423 priv->draft_msg = NULL;
424 priv->outbox_msg = NULL;
425 priv->msg_uid = NULL;
427 priv->can_undo = FALSE;
428 priv->can_redo = FALSE;
429 priv->clipboard_change_handler_id = 0;
430 priv->default_clipboard_change_handler_id = 0;
431 priv->account_removed_handler_id = 0;
432 priv->clipboard_owner_idle = 0;
433 priv->clipboard_text = NULL;
436 priv->scroll_drag_timeout_id = 0;
437 priv->last_upper = 0.0;
439 priv->font_dialog = NULL;
441 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
442 GTK_WINDOW(obj),"applications_email_editor");
444 if (!is_wp_text_buffer_started) {
445 is_wp_text_buffer_started = TRUE;
446 wp_text_buffer_library_init ();
451 hildon_program_add_window (hildon_program_get_instance(),
457 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
459 static ModestPairList*
460 get_transports (void)
462 GSList *transports = NULL;
464 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
465 GSList *accounts = modest_account_mgr_account_names (account_mgr,
466 TRUE /* only enabled accounts. */);
468 GSList *cursor = accounts;
470 gchar *account_name = cursor->data;
471 gchar *from_string = NULL;
473 from_string = modest_account_mgr_get_from_string (account_mgr,
477 if (from_string && account_name) {
478 gchar *name = account_name;
479 ModestPair *pair = modest_pair_new ((gpointer) name,
480 (gpointer) from_string , TRUE);
481 transports = g_slist_prepend (transports, pair);
484 cursor = cursor->next;
486 g_slist_free (accounts); /* only free the accounts, not the elements,
487 * because they are used in the pairlist */
491 static void window_focus (GtkWindow *window,
495 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
499 scroll_drag_timeout (gpointer userdata)
501 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
502 ModestMsgEditWindowPrivate *priv;
504 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
506 correct_scroll_without_drag_check (win, TRUE);
508 priv->scroll_drag_timeout_id = 0;
514 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
516 ModestMsgEditWindowPrivate *priv;
519 GdkRectangle rectangle;
523 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
525 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
528 insert = gtk_text_buffer_get_insert (priv->text_buffer);
529 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
531 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
532 offset = priv->msg_body->allocation.y;
534 new_value = (offset + rectangle.y);
536 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (priv->pannable), -1, new_value);
540 correct_scroll (ModestMsgEditWindow *w)
542 ModestMsgEditWindowPrivate *priv;
544 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
545 if (gtk_grab_get_current () == priv->msg_body) {
546 if (priv->scroll_drag_timeout_id == 0) {
547 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
553 correct_scroll_without_drag_check (w, TRUE);
557 text_buffer_end_user_action (GtkTextBuffer *buffer,
558 ModestMsgEditWindow *userdata)
561 correct_scroll (userdata);
565 text_buffer_mark_set (GtkTextBuffer *buffer,
568 ModestMsgEditWindow *userdata)
570 gtk_text_buffer_begin_user_action (buffer);
571 gtk_text_buffer_end_user_action (buffer);
575 cut_clipboard_check (GtkTextView *text_view,
578 GtkTextBuffer *buffer;
580 buffer = gtk_text_view_get_buffer (text_view);
581 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
582 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
587 copy_clipboard_check (GtkTextView *text_view,
590 GtkTextBuffer *buffer;
592 buffer = gtk_text_view_get_buffer (text_view);
593 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
594 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
599 attachment_deleted (ModestAttachmentsView *attachments_view,
602 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
607 connect_signals (ModestMsgEditWindow *obj)
609 ModestMsgEditWindowPrivate *priv;
611 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
613 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
614 G_CALLBACK (text_buffer_refresh_attributes), obj);
615 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
616 G_CALLBACK (text_buffer_can_undo), obj);
617 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
618 G_CALLBACK (text_buffer_can_redo), obj);
619 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
620 G_CALLBACK (body_changed), obj);
621 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
622 G_CALLBACK (body_changed), obj);
623 g_signal_connect (G_OBJECT (obj), "window-state-event",
624 G_CALLBACK (modest_msg_edit_window_window_state_event),
626 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
627 G_CALLBACK (text_buffer_end_user_action), obj);
628 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
629 G_CALLBACK (text_buffer_mark_set), obj);
630 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
631 G_CALLBACK (text_buffer_apply_tag), obj);
632 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
633 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
634 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
635 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
636 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
637 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
639 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
640 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
642 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
643 G_CALLBACK (msg_body_focus), obj);
644 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
645 G_CALLBACK (msg_body_focus), obj);
646 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
647 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
648 "changed", G_CALLBACK (recpt_field_changed), obj);
649 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
650 "changed", G_CALLBACK (recpt_field_changed), obj);
651 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
652 "changed", G_CALLBACK (recpt_field_changed), obj);
653 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
654 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
655 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
657 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
658 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
660 priv->clipboard_change_handler_id =
661 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
662 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
663 priv->default_clipboard_change_handler_id =
664 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
665 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
667 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
668 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
669 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
673 init_window (ModestMsgEditWindow *obj)
675 GtkWidget *to_caption, *subject_caption;
676 GtkWidget *main_vbox;
677 ModestMsgEditWindowPrivate *priv;
678 GtkActionGroup *action_group;
679 ModestWindowPrivate *parent_priv;
680 GdkPixbuf *window_icon = NULL;
681 GError *error = NULL;
683 GtkSizeGroup *title_size_group;
684 GtkSizeGroup *value_size_group;
685 GtkWidget *subject_box;
686 GtkWidget *attachment_icon;
687 GtkWidget *window_box;
688 #if (GTK_MINOR_VERSION >= 10)
689 GdkAtom deserialize_type;
692 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
693 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
695 parent_priv->ui_manager = gtk_ui_manager_new();
696 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
697 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
699 /* Add common actions */
700 gtk_action_group_add_actions (action_group,
701 modest_msg_edit_action_entries,
702 G_N_ELEMENTS (modest_msg_edit_action_entries),
704 gtk_action_group_add_toggle_actions (action_group,
705 modest_msg_edit_toggle_action_entries,
706 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
708 gtk_action_group_add_radio_actions (action_group,
709 modest_msg_edit_alignment_radio_action_entries,
710 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
712 G_CALLBACK (modest_ui_actions_on_change_justify),
714 gtk_action_group_add_radio_actions (action_group,
715 modest_msg_edit_priority_action_entries,
716 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
718 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
720 gtk_action_group_add_radio_actions (action_group,
721 modest_msg_edit_file_format_action_entries,
722 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
723 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
724 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
726 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
727 g_object_unref (action_group);
729 /* Load the UI definition */
730 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
733 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
734 g_clear_error (&error);
737 /* Add accelerators */
738 gtk_window_add_accel_group (GTK_WINDOW (obj),
739 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
741 parent_priv->menubar = NULL;
743 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
744 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
746 /* Note: This ModestPairList* must exist for as long as the picker
747 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
748 * so it can't know how to manage its memory. */
749 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
750 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
752 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
753 _("mail_va_from"), priv->from_field);
755 priv->to_field = modest_recpt_editor_new ();
756 priv->cc_field = modest_recpt_editor_new ();
757 priv->bcc_field = modest_recpt_editor_new ();
758 subject_box = gtk_hbox_new (FALSE, 0);
759 priv->priority_icon = gtk_image_new ();
760 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
761 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
762 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
763 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
764 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
765 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
766 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
767 priv->add_attachment_button = gtk_button_new ();
768 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
769 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
770 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
771 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 0.5);
772 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
773 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
774 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
775 priv->attachments_view = modest_attachments_view_new (NULL);
777 priv->header_box = gtk_vbox_new (FALSE, 0);
779 to_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
780 _("mail_va_to"), priv->to_field);
781 priv->cc_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
782 _("mail_va_cc"), priv->cc_field);
783 priv->bcc_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
784 _("mail_va_hotfix1"), priv->bcc_field);
785 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
786 _("mail_va_subject"), subject_box);
787 priv->attachments_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
788 _("mail_va_attachment"),
789 priv->attachments_view);
790 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
791 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
792 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
793 g_object_unref (title_size_group);
794 g_object_unref (value_size_group);
796 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
797 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
798 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
799 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
800 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
801 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
802 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
805 priv->msg_body = wp_text_view_new ();
806 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
807 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
808 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
809 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
810 #if (GTK_MINOR_VERSION >= 10)
811 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
812 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
814 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
815 deserialize_type, TRUE);
817 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
819 priv->find_toolbar = hildon_find_toolbar_new (NULL);
820 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
822 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
824 priv->pannable = hildon_pannable_area_new ();
826 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
828 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
829 priv->frame = gtk_frame_new (NULL);
830 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
832 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), main_vbox);
833 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
835 window_box = gtk_vbox_new (FALSE, 0);
836 gtk_container_add (GTK_CONTAINER(obj), window_box);
838 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
840 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
842 /* Set window icon */
843 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
845 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
846 g_object_unref (window_icon);
851 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
853 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
855 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
856 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
857 priv->clipboard_change_handler_id))
858 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
859 priv->clipboard_change_handler_id);
860 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
861 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
862 priv->default_clipboard_change_handler_id))
863 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
864 priv->default_clipboard_change_handler_id);
866 if (priv->account_removed_handler_id &&
867 g_signal_handler_is_connected (modest_runtime_get_account_store (),
868 priv->account_removed_handler_id))
869 g_signal_handler_disconnect(modest_runtime_get_account_store (),
870 priv->account_removed_handler_id);
874 modest_msg_edit_window_finalize (GObject *obj)
876 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
878 /* Sanity check: shouldn't be needed, the window mgr should
879 call this function before */
880 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
882 if (priv->font_dialog != NULL) {
883 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
886 if (priv->clipboard_text != NULL) {
887 g_free (priv->clipboard_text);
888 priv->clipboard_text = NULL;
891 if (priv->draft_msg != NULL) {
892 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
893 if (TNY_IS_HEADER (header)) {
894 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
895 modest_window_mgr_unregister_header (mgr, header);
897 g_object_unref (priv->draft_msg);
898 priv->draft_msg = NULL;
900 if (priv->outbox_msg != NULL) {
901 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
902 if (TNY_IS_HEADER (header)) {
903 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
904 modest_window_mgr_unregister_header (mgr, header);
906 g_object_unref (priv->outbox_msg);
907 priv->outbox_msg = NULL;
909 if (priv->scroll_drag_timeout_id > 0) {
910 g_source_remove (priv->scroll_drag_timeout_id);
911 priv->scroll_drag_timeout_id = 0;
913 if (priv->clipboard_owner_idle > 0) {
914 g_source_remove (priv->clipboard_owner_idle);
915 priv->clipboard_owner_idle = 0;
917 if (priv->original_account_name)
918 g_free (priv->original_account_name);
919 g_free (priv->msg_uid);
920 g_free (priv->last_search);
921 g_slist_free (priv->font_items_group);
922 g_slist_free (priv->size_items_group);
923 g_object_unref (priv->attachments);
924 g_object_unref (priv->images);
926 /* This had to stay alive for as long as the picker that used it: */
927 modest_pair_list_free (priv->from_field_protos);
929 G_OBJECT_CLASS(parent_class)->finalize (obj);
933 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
935 GdkPixbufLoader *loader;
941 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
943 if (loader == NULL) {
949 tny_stream_reset (TNY_STREAM (stream));
950 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
951 GError *error = NULL;
952 unsigned char read_buffer[128];
954 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
956 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
958 g_error_free (error);
963 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
965 g_object_ref (pixbuf);
966 gdk_pixbuf_loader_close (loader, NULL);
967 g_object_unref (loader);
972 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
973 GdkPixbuf *new_pixbuf;
975 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
976 gdk_pixbuf_get_width (pixbuf);
977 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
978 g_object_unref (pixbuf);
989 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
991 ModestMsgEditWindowPrivate *priv;
994 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
996 for (iter = tny_list_create_iterator (attachments);
997 !tny_iterator_is_done (iter);
998 tny_iterator_next (iter)) {
999 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1000 const gchar *cid = tny_mime_part_get_content_id (part);
1001 const gchar *mime_type = tny_mime_part_get_content_type (part);
1002 if ((cid != NULL)&&(mime_type != NULL)) {
1003 guint64 stream_size;
1004 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1005 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1008 g_object_unref (stream);
1010 if (pixbuf != NULL) {
1011 priv->images_count ++;
1012 priv->images_size += stream_size;
1013 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1014 g_object_unref (pixbuf);
1017 g_object_unref (part);
1019 g_object_unref (iter);
1023 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1025 TnyMimePart *parent = NULL;
1026 const gchar *content_type = NULL;
1027 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1029 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1031 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1032 parent = g_object_ref (msg);
1033 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1034 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1037 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1038 iter = tny_list_create_iterator (parts);
1039 while (!tny_iterator_is_done (iter)) {
1041 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1042 content_type = tny_mime_part_get_content_type (part);
1043 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1047 g_object_unref (part);
1049 tny_iterator_next (iter);
1051 g_object_unref (iter);
1052 g_object_unref (parts);
1055 if (parent != NULL) {
1056 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1059 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1060 iter = tny_list_create_iterator (parts);
1061 while (!tny_iterator_is_done (iter)) {
1063 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1064 content_type = tny_mime_part_get_content_type (part);
1065 if (content_type && g_str_has_prefix (content_type, "image/")) {
1066 tny_list_prepend (priv->images, (GObject *) part);
1068 g_object_unref (part);
1069 tny_iterator_next (iter);
1071 g_object_unref (iter);
1072 g_object_unref (parts);
1073 g_object_unref (parent);
1078 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1081 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1083 for (iter = tny_list_create_iterator (attachments) ;
1084 !tny_iterator_is_done (iter);
1085 tny_iterator_next (iter)) {
1086 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1087 const gchar *cid = tny_mime_part_get_content_id (part);
1089 char *invalid = NULL;
1090 gint int_cid = strtol (cid, &invalid, 10);
1091 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1092 priv->next_cid = int_cid + 1;
1095 g_object_unref (part);
1097 g_object_unref (iter);
1101 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1104 gchar *to, *cc, *bcc, *subject;
1106 ModestMsgEditWindowPrivate *priv;
1108 TnyHeaderFlags priority_flags;
1109 TnyFolder *msg_folder;
1110 gboolean is_html = FALSE;
1112 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1113 g_return_if_fail (TNY_IS_MSG (msg));
1115 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1117 header = tny_msg_get_header (msg);
1118 to = tny_header_dup_to (header);
1119 cc = tny_header_dup_cc (header);
1120 bcc = tny_header_dup_bcc (header);
1121 subject = tny_header_dup_subject (header);
1122 priority_flags = tny_header_get_priority (header);
1125 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1127 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1128 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1129 gtk_widget_show (priv->cc_caption);
1130 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1131 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1132 gtk_widget_hide (priv->cc_caption);
1135 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1136 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1137 gtk_widget_show (priv->bcc_caption);
1138 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1139 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1140 gtk_widget_hide (priv->bcc_caption);
1143 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1144 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1147 update_window_title (self);
1149 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1150 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1152 if ((body == NULL)||(body[0] == '\0')) {
1154 body = modest_text_utils_convert_to_html ("");
1157 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1158 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1161 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1164 /* Add attachments to the view */
1165 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1166 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1167 if (tny_list_get_length (priv->attachments) == 0) {
1168 gtk_widget_hide (priv->attachments_caption);
1170 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1171 gtk_widget_show_all (priv->attachments_caption);
1173 get_related_images (self, msg);
1174 update_next_cid (self, priv->attachments);
1175 update_next_cid (self, priv->images);
1176 replace_with_images (self, priv->images);
1178 if (preserve_is_rich && !is_html) {
1179 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1180 /* Get the default format required from configuration */
1181 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1182 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1185 /* Set the default focus depending on having already a To: field or not */
1186 if ((!to)||(*to == '\0')) {
1187 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1189 gtk_widget_grab_focus (priv->msg_body);
1192 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1194 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1195 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1197 modest_msg_edit_window_set_modified (self, FALSE);
1199 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1200 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1201 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1202 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1204 if (priv->msg_uid) {
1205 g_free (priv->msg_uid);
1206 priv->msg_uid = NULL;
1209 /* we should set a reference to the incoming message if it is a draft */
1210 msg_folder = tny_msg_get_folder (msg);
1212 if (modest_tny_folder_is_local_folder (msg_folder)) {
1213 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1214 if (type == TNY_FOLDER_TYPE_INVALID)
1215 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1217 if (type == TNY_FOLDER_TYPE_DRAFTS)
1218 priv->draft_msg = g_object_ref(msg);
1219 if (type == TNY_FOLDER_TYPE_OUTBOX)
1220 priv->outbox_msg = g_object_ref(msg);
1221 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1223 g_object_unref (msg_folder);
1233 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1236 GList *item_children, *node;
1237 GtkWidget *bin_child;
1239 bin_child = gtk_bin_get_child (GTK_BIN(item));
1241 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1243 for (node = item_children; node != NULL; node = g_list_next (node)) {
1244 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1245 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1248 g_list_free (item_children);
1252 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1255 GList *item_children, *node;
1257 box = gtk_bin_get_child (GTK_BIN (item));
1258 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1259 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1261 for (node = item_children; node != NULL; node = g_list_next (node)) {
1262 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1263 if (GTK_IS_TOGGLE_BUTTON (node->data))
1264 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1265 else if (GTK_IS_BUTTON (node->data))
1266 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1268 g_list_free (item_children);
1273 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1275 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1276 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1277 GtkWidget *placeholder;
1278 GtkWidget *tool_item;
1283 GtkWidget *sizes_menu;
1284 GtkWidget *fonts_menu;
1285 GSList *radio_group = NULL;
1286 GSList *node = NULL;
1290 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1291 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1293 /* Font color placeholder */
1294 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1295 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1298 tool_item = GTK_WIDGET (gtk_tool_item_new ());
1299 priv->font_color_button = hildon_color_button_new ();
1300 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1301 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1302 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
1303 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1304 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1305 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1306 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1308 G_CALLBACK (modest_msg_edit_window_color_button_change),
1311 /* Font size and face placeholder */
1312 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1313 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1315 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1316 priv->size_tool_button_label = gtk_label_new (NULL);
1317 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1318 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1319 size_text,"</span>", NULL);
1320 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1322 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1323 sizes_menu = gtk_menu_new ();
1324 priv->size_items_group = NULL;
1326 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1327 GtkWidget *size_menu_item;
1329 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1330 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1331 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1332 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1333 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1334 gtk_widget_show (size_menu_item);
1336 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1340 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1341 GtkWidget *item = (GtkWidget *) node->data;
1342 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1346 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1347 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1348 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1349 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1350 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1351 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1352 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1353 priv->font_size_toolitem = tool_item;
1356 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1357 priv->font_tool_button_label = gtk_label_new (NULL);
1358 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1359 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1361 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1362 fonts_menu = gtk_menu_new ();
1363 priv->font_items_group = NULL;
1365 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1366 GtkWidget *font_menu_item;
1367 GtkWidget *child_label;
1369 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1370 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1371 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1372 wp_get_font_name (font_index), "</span>", NULL);
1373 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1376 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1377 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1378 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1379 gtk_widget_show (font_menu_item);
1381 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1384 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1385 GtkWidget *item = (GtkWidget *) node->data;
1386 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1389 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1390 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1391 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1392 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1393 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1394 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1395 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1396 priv->font_face_toolitem = tool_item;
1398 /* Set expand and homogeneous for remaining items */
1399 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1400 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1401 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1402 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1403 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1404 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1405 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1406 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1407 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1409 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1410 will not show the tool items added to the placeholders) */
1411 gtk_widget_show_all (parent_priv->toolbar);
1413 /* Set the no show all *after* showing all items. We do not
1414 want the toolbar to be shown with a show all because it
1415 could go agains the gconf setting regarding showing or not
1416 the toolbar of the editor window */
1417 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1423 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1426 ModestWindowPrivate *parent_priv;
1427 ModestMsgEditWindowPrivate *priv;
1428 ModestDimmingRulesGroup *menu_rules_group = NULL;
1429 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1430 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1431 ModestWindowMgr *mgr = NULL;
1433 g_return_val_if_fail (msg, NULL);
1434 g_return_val_if_fail (account_name, NULL);
1436 mgr = modest_runtime_get_window_mgr ();
1438 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1440 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1441 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1443 /* Menubar. Update the state of some toggles */
1444 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1445 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1446 priv->from_field_protos = get_transports ();
1447 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1448 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1449 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1451 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1452 hildon_touch_selector_get_current_text
1453 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1454 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1455 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1458 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1460 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1462 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1464 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1466 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1467 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1468 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1469 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1470 /* Add common dimming rules */
1471 modest_dimming_rules_group_add_rules (menu_rules_group,
1472 modest_msg_edit_window_menu_dimming_entries,
1473 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1474 MODEST_WINDOW (obj));
1475 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1476 modest_msg_edit_window_toolbar_dimming_entries,
1477 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1478 MODEST_WINDOW (obj));
1479 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1480 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1481 MODEST_WINDOW (obj));
1482 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1483 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1484 MODEST_WINDOW (obj));
1485 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1486 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1487 MODEST_WINDOW (obj));
1488 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1489 modest_msg_edit_window_clipboard_dimming_entries,
1490 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1491 MODEST_WINDOW (obj));
1492 /* Insert dimming rules group for this window */
1493 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1494 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1495 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1496 /* Checks the dimming rules */
1497 g_object_unref (menu_rules_group);
1498 g_object_unref (toolbar_rules_group);
1499 g_object_unref (clipboard_rules_group);
1500 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1502 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1504 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1505 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1506 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1507 priv->update_caption_visibility = TRUE;
1509 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1511 /* Track account-removed signal, this window should be closed
1512 in the case we're creating a mail associated to the account
1514 priv->account_removed_handler_id =
1515 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1517 G_CALLBACK(on_account_removed),
1520 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1522 return (ModestWindow*) obj;
1526 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1528 GString **string_buffer = (GString **) user_data;
1530 *string_buffer = g_string_append (*string_buffer, buffer);
1536 * @result: A new string which should be freed with g_free().
1539 get_formatted_data (ModestMsgEditWindow *edit_window)
1541 ModestMsgEditWindowPrivate *priv;
1542 GString *string_buffer = g_string_new ("");
1544 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1546 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1548 modest_text_utils_hyperlinkify (string_buffer);
1550 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1552 return g_string_free (string_buffer, FALSE);
1557 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1560 const gchar *account_name;
1561 ModestMsgEditWindowPrivate *priv;
1562 TnyIterator *att_iter;
1564 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1566 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1568 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1569 g_return_val_if_fail (account_name, NULL);
1572 /* don't free these (except from) */
1573 data = g_slice_new0 (MsgData);
1574 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1576 data->account_name = g_strdup (account_name);
1577 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1578 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1579 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1580 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1581 if (priv->draft_msg) {
1582 data->draft_msg = g_object_ref (priv->draft_msg);
1583 } else if (priv->outbox_msg) {
1584 data->draft_msg = g_object_ref (priv->outbox_msg);
1586 data->draft_msg = NULL;
1589 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1591 gtk_text_buffer_get_bounds (buf, &b, &e);
1592 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1594 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1595 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1597 data->html_body = NULL;
1599 /* deep-copy the data */
1600 att_iter = tny_list_create_iterator (priv->attachments);
1601 data->attachments = NULL;
1602 while (!tny_iterator_is_done (att_iter)) {
1603 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1604 if (!(TNY_IS_MIME_PART(part))) {
1605 g_warning ("strange data in attachment list");
1606 g_object_unref (part);
1607 tny_iterator_next (att_iter);
1610 data->attachments = g_list_append (data->attachments,
1612 tny_iterator_next (att_iter);
1614 g_object_unref (att_iter);
1616 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1617 att_iter = tny_list_create_iterator (priv->images);
1618 data->images = NULL;
1619 while (!tny_iterator_is_done (att_iter)) {
1620 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1622 if (!(TNY_IS_MIME_PART(part))) {
1623 g_warning ("strange data in attachment list");
1624 g_object_unref (part);
1625 tny_iterator_next (att_iter);
1628 cid = tny_mime_part_get_content_id (part);
1630 gchar *image_tag_id;
1631 GtkTextTag *image_tag;
1633 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1634 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1635 g_free (image_tag_id);
1637 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1639 ((gtk_text_iter_has_tag (&iter, image_tag))||
1640 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1641 data->images = g_list_append (data->images,
1642 g_object_ref (part));
1644 g_object_unref (part);
1645 tny_iterator_next (att_iter);
1647 g_object_unref (att_iter);
1649 data->priority_flags = priv->priority_flags;
1656 unref_gobject (GObject *obj, gpointer data)
1658 if (!G_IS_OBJECT(obj))
1660 g_object_unref (obj);
1664 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1667 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1675 g_free (data->from);
1676 g_free (data->subject);
1677 g_free (data->plain_body);
1678 g_free (data->html_body);
1679 g_free (data->account_name);
1681 if (data->draft_msg != NULL) {
1682 g_object_unref (data->draft_msg);
1683 data->draft_msg = NULL;
1686 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1687 g_list_free (data->attachments);
1688 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1689 g_list_free (data->images);
1691 g_slice_free (MsgData, data);
1695 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1697 guint64 *parts_size)
1699 ModestMsgEditWindowPrivate *priv;
1701 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1703 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1705 /* TODO: add images */
1706 *parts_size += priv->images_size;
1707 *parts_count += priv->images_count;
1712 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1715 ModestMsgEditWindowPrivate *priv = NULL;
1716 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1718 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1720 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1722 return MODEST_MSG_EDIT_FORMAT_HTML;
1724 return MODEST_MSG_EDIT_FORMAT_TEXT;
1728 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1729 ModestMsgEditFormat format)
1731 ModestMsgEditWindowPrivate *priv;
1733 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1734 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1737 case MODEST_MSG_EDIT_FORMAT_HTML:
1738 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1740 case MODEST_MSG_EDIT_FORMAT_TEXT:
1741 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1744 g_return_if_reached ();
1748 ModestMsgEditFormatState *
1749 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1751 ModestMsgEditFormatState *format_state = NULL;
1752 ModestMsgEditWindowPrivate *priv;
1753 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1755 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1756 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1758 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1760 format_state = g_new0 (ModestMsgEditFormatState, 1);
1761 format_state->bold = buffer_format->bold&0x1;
1762 format_state->italics = buffer_format->italic&0x1;
1763 format_state->bullet = buffer_format->bullet&0x1;
1764 format_state->color = buffer_format->color;
1765 format_state->font_size = buffer_format->font_size;
1766 format_state->font_family = wp_get_font_name (buffer_format->font);
1767 format_state->justification = buffer_format->justification;
1768 g_free (buffer_format);
1770 return format_state;
1775 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1776 const ModestMsgEditFormatState *format_state)
1778 ModestMsgEditWindowPrivate *priv;
1779 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1780 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1781 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1782 g_return_if_fail (format_state != NULL);
1784 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1785 gtk_widget_grab_focus (priv->msg_body);
1786 buffer_format->bold = (format_state->bold != FALSE);
1787 buffer_format->italic = (format_state->italics != FALSE);
1788 buffer_format->color = format_state->color;
1789 buffer_format->font_size = format_state->font_size;
1790 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1791 buffer_format->justification = format_state->justification;
1792 buffer_format->bullet = format_state->bullet;
1794 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1796 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1797 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1798 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1799 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1800 buffer_format->cs.font = (buffer_format->font != current_format->font);
1801 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1802 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1804 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1805 if (buffer_format->cs.bold) {
1806 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1807 GINT_TO_POINTER (buffer_format->bold&0x1));
1809 if (buffer_format->cs.italic) {
1810 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1811 GINT_TO_POINTER (buffer_format->italic&0x1));
1813 if (buffer_format->cs.color) {
1814 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1815 GINT_TO_POINTER (&(buffer_format->color)));
1817 if (buffer_format->cs.font_size) {
1818 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1819 GINT_TO_POINTER (buffer_format->font_size));
1821 if (buffer_format->cs.justification) {
1822 switch (buffer_format->justification) {
1823 case GTK_JUSTIFY_LEFT:
1824 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1825 GINT_TO_POINTER(TRUE));
1827 case GTK_JUSTIFY_CENTER:
1828 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1829 GINT_TO_POINTER(TRUE));
1831 case GTK_JUSTIFY_RIGHT:
1832 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1833 GINT_TO_POINTER(TRUE));
1840 if (buffer_format->cs.font) {
1841 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1842 GINT_TO_POINTER (buffer_format->font));
1844 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1845 if (buffer_format->cs.bullet) {
1846 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1847 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1849 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1851 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1853 g_free (buffer_format);
1854 g_free (current_format);
1856 /* Check dimming rules */
1857 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1858 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1862 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1864 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1866 ModestWindowPrivate *parent_priv;
1867 ModestMsgEditWindowPrivate *priv;
1868 GtkWidget *new_size_menuitem;
1869 GtkWidget *new_font_menuitem;
1871 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1872 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1874 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1875 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1876 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1877 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1879 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1880 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1881 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1884 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1886 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1887 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1889 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1890 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1892 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1893 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1896 switch (buffer_format->justification)
1898 case GTK_JUSTIFY_LEFT:
1899 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1901 case GTK_JUSTIFY_CENTER:
1902 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1904 case GTK_JUSTIFY_RIGHT:
1905 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1912 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1914 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1915 G_CALLBACK (modest_msg_edit_window_color_button_change),
1917 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1918 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1919 G_CALLBACK (modest_msg_edit_window_color_button_change),
1922 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1923 buffer_format->font_size))->data);
1924 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1928 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1929 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1930 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1932 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1933 G_CALLBACK (modest_msg_edit_window_size_change),
1935 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1936 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1937 G_CALLBACK (modest_msg_edit_window_size_change),
1941 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1942 buffer_format->font))->data);
1943 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1947 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1948 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1949 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1951 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1952 G_CALLBACK (modest_msg_edit_window_font_change),
1954 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1955 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1956 G_CALLBACK (modest_msg_edit_window_font_change),
1960 g_free (buffer_format);
1964 #ifdef MODEST_HILDON_VERSION_0
1966 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1969 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1970 ModestMsgEditWindowPrivate *priv;
1971 GtkWidget *dialog = NULL;
1973 GdkColor *new_color = NULL;
1975 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1976 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1978 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1979 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1980 g_free (buffer_format);
1982 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
1983 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1984 if (new_color != NULL) {
1985 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1986 (gpointer) new_color);
1989 gtk_widget_destroy (dialog);
1994 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1997 ModestMsgEditWindowPrivate *priv;
1998 GtkWidget *dialog = NULL;
2000 GdkColor *old_color = NULL;
2001 const GdkColor *new_color = NULL;
2003 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2004 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2006 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2007 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2009 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2010 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2011 if (new_color != NULL)
2012 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2014 gtk_widget_destroy (dialog);
2020 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2023 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2024 ModestMsgEditWindowPrivate *priv;
2025 GtkWidget *dialog = NULL;
2027 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2028 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2030 dialog = hildon_color_chooser_new ();
2031 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2032 g_free (buffer_format);
2034 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2036 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2037 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2040 gtk_widget_destroy (dialog);
2045 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2048 ModestMsgEditWindowPrivate *priv;
2049 GtkWidget *dialog = NULL;
2050 GdkColor *old_color = NULL;
2052 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2053 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2055 dialog = hildon_color_chooser_new ();
2056 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2058 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2060 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2061 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2063 gtk_widget_destroy (dialog);
2066 #endif /*!MODEST_HILDON_VERSION_0*/
2071 create_stream_for_uri (const gchar* uri)
2076 TnyStream *result = NULL;
2078 GnomeVFSHandle *handle = NULL;
2079 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2080 if (test == GNOME_VFS_OK) {
2081 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2082 /* Streams over OBEX (Bluetooth) are not seekable but
2083 * we expect them to be (we might need to read them
2084 * several times). So if this is a Bluetooth URI just
2085 * read the whole file into memory (this is not a fast
2086 * protocol so we can assume that these files are not
2087 * going to be very big) */
2088 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2089 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2090 TnyStream *memstream = tny_camel_mem_stream_new ();
2091 tny_stream_write_to_stream (vfssstream, memstream);
2092 g_object_unref (vfssstream);
2095 result = vfssstream;
2103 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2106 ModestMsgEditWindowPrivate *priv;
2107 GtkWidget *dialog = NULL;
2109 GSList *uris = NULL;
2110 GSList *uri_node = NULL;
2112 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2114 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2115 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2116 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2118 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2120 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2121 GTK_WINDOW (dialog), GTK_WINDOW (window));
2123 response = gtk_dialog_run (GTK_DIALOG (dialog));
2125 case GTK_RESPONSE_OK:
2126 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2131 gtk_widget_destroy (dialog);
2133 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2135 GnomeVFSHandle *handle = NULL;
2136 GnomeVFSResult result;
2137 GtkTextIter position;
2138 GtkTextMark *insert_mark;
2140 uri = (const gchar *) uri_node->data;
2141 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2142 if (result == GNOME_VFS_OK) {
2144 GnomeVFSFileInfo *info;
2145 gchar *filename, *basename, *escaped_filename;
2146 TnyMimePart *mime_part;
2148 const gchar *mime_type = NULL;
2149 GnomeVFSURI *vfs_uri;
2150 guint64 stream_size;
2152 gnome_vfs_close (handle);
2153 vfs_uri = gnome_vfs_uri_new (uri);
2155 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2156 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2157 g_free (escaped_filename);
2158 gnome_vfs_uri_unref (vfs_uri);
2159 info = gnome_vfs_file_info_new ();
2161 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2162 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2164 mime_type = gnome_vfs_file_info_get_mime_type (info);
2166 mime_part = tny_platform_factory_new_mime_part
2167 (modest_runtime_get_platform_factory ());
2169 TnyStream *stream = create_stream_for_uri (uri);
2171 if (stream == NULL) {
2173 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2175 g_object_unref (mime_part);
2176 gnome_vfs_file_info_unref (info);
2180 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2182 content_id = g_strdup_printf ("%d", priv->next_cid);
2183 tny_mime_part_set_content_id (mime_part, content_id);
2184 g_free (content_id);
2187 basename = g_path_get_basename (filename);
2188 tny_mime_part_set_filename (mime_part, basename);
2191 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2193 if (pixbuf != NULL) {
2194 priv->images_size += stream_size;
2195 priv->images_count ++;
2196 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2197 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2198 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2199 g_object_unref (pixbuf);
2202 tny_list_prepend (priv->images, (GObject *) mime_part);
2203 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2205 g_object_unref (mime_part);
2206 gnome_vfs_file_info_unref (info);
2215 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2217 GtkWidget *dialog = NULL;
2219 GSList *uris = NULL;
2221 GnomeVFSFileSize total_size, allowed_size;
2222 ModestMsgEditWindowPrivate *priv;
2226 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2228 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2230 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2233 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2234 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2235 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2236 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), GTK_WINDOW (window));
2238 response = gtk_dialog_run (GTK_DIALOG (dialog));
2240 case GTK_RESPONSE_OK:
2241 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2246 gtk_widget_destroy (dialog);
2248 /* allowed size is the maximum size - what's already there */
2249 modest_attachments_view_get_sizes (
2250 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2251 &att_num, &att_size);
2252 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2255 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2257 const gchar *uri = (const gchar *) uri_node->data;
2259 total_size += modest_msg_edit_window_attach_file_one
2260 (window, uri, allowed_size);
2262 if (total_size > allowed_size) {
2263 g_warning ("%s: total size: %u",
2264 __FUNCTION__, (unsigned int)total_size);
2268 allowed_size -= total_size;
2272 g_slist_foreach (uris, (GFunc) g_free, NULL);
2273 g_slist_free (uris);
2278 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2280 GnomeVFSFileSize allowed_size)
2283 GnomeVFSHandle *handle = NULL;
2284 ModestMsgEditWindowPrivate *priv;
2285 GnomeVFSResult result;
2286 GnomeVFSFileSize size = 0;
2287 g_return_val_if_fail (window, 0);
2288 g_return_val_if_fail (uri, 0);
2290 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2292 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2293 if (result == GNOME_VFS_OK) {
2294 TnyMimePart *mime_part;
2296 const gchar *mime_type = NULL;
2298 gchar *escaped_filename;
2301 GnomeVFSFileInfo *info;
2302 GnomeVFSURI *vfs_uri;
2304 gnome_vfs_close (handle);
2305 vfs_uri = gnome_vfs_uri_new (uri);
2308 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2309 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2310 g_free (escaped_filename);
2311 gnome_vfs_uri_unref (vfs_uri);
2313 info = gnome_vfs_file_info_new ();
2315 if (gnome_vfs_get_file_info (uri,
2317 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2319 mime_type = gnome_vfs_file_info_get_mime_type (info);
2320 mime_part = tny_platform_factory_new_mime_part
2321 (modest_runtime_get_platform_factory ());
2323 /* try to get the attachment's size; this may fail for weird
2324 * file systems, like obex, upnp... */
2325 if (allowed_size != 0 &&
2326 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2328 if (size > allowed_size) {
2329 modest_platform_information_banner (NULL, NULL,
2330 dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2334 g_warning ("%s: could not get attachment size", __FUNCTION__);
2336 stream = create_stream_for_uri (uri);
2338 if (stream == NULL) {
2340 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2342 g_object_unref (mime_part);
2343 gnome_vfs_file_info_unref (info);
2347 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2348 g_object_unref (stream);
2350 content_id = g_strdup_printf ("%d", priv->next_cid);
2351 tny_mime_part_set_content_id (mime_part, content_id);
2352 g_free (content_id);
2355 basename = g_path_get_basename (filename);
2356 tny_mime_part_set_filename (mime_part, basename);
2359 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2360 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2362 info->size == 0, info->size);
2363 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2364 gtk_widget_show_all (priv->attachments_caption);
2365 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2367 g_object_unref (mime_part);
2368 gnome_vfs_file_info_unref (info);
2375 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2378 ModestMsgEditWindowPrivate *priv;
2381 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2382 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2384 if (att_list == NULL) {
2385 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2387 g_object_ref (att_list);
2390 if (tny_list_get_length (att_list) == 0) {
2391 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2393 gboolean dialog_response;
2394 gchar *message = NULL;
2395 gchar *filename = NULL;
2397 if (tny_list_get_length (att_list) == 1) {
2399 iter = tny_list_create_iterator (att_list);
2400 part = (TnyMimePart *) tny_iterator_get_current (iter);
2401 g_object_unref (iter);
2402 if (TNY_IS_MSG (part)) {
2403 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2405 filename = tny_header_dup_subject (header);
2406 g_object_unref (header);
2408 if (filename == NULL) {
2409 filename = g_strdup (_("mail_va_no_subject"));
2412 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2414 g_object_unref (part);
2416 filename = g_strdup ("");
2418 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2419 tny_list_get_length (att_list)), filename);
2422 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2425 if (dialog_response != GTK_RESPONSE_OK) {
2426 g_object_unref (att_list);
2429 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
2431 for (iter = tny_list_create_iterator (att_list);
2432 !tny_iterator_is_done (iter);
2433 tny_iterator_next (iter)) {
2434 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2435 const gchar *att_id;
2436 tny_list_remove (priv->attachments, (GObject *) mime_part);
2438 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2440 if (tny_list_get_length (priv->attachments) == 0)
2441 gtk_widget_hide (priv->attachments_caption);
2442 att_id = tny_mime_part_get_content_id (mime_part);
2444 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2446 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2447 g_object_unref (mime_part);
2449 g_object_unref (iter);
2452 g_object_unref (att_list);
2454 /* if the last attachment has been removed, focus the Subject: field */
2455 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2456 gtk_widget_grab_focus (priv->subject_field);
2460 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2463 ModestMsgEditWindowPrivate *priv;
2464 GdkColor *new_color;
2465 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2467 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2468 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2471 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2473 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2475 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2477 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2482 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2485 ModestMsgEditWindowPrivate *priv;
2486 gint new_size_index;
2487 ModestMsgEditWindow *window;
2490 window = MODEST_MSG_EDIT_WINDOW (userdata);
2491 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2492 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2494 if (gtk_check_menu_item_get_active (menu_item)) {
2496 WPTextBufferFormat format;
2498 memset (&format, 0, sizeof (format));
2499 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2501 label = gtk_bin_get_child (GTK_BIN (menu_item));
2503 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2504 format.cs.font_size = TRUE;
2505 format.cs.text_position = TRUE;
2506 format.cs.font = TRUE;
2507 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2508 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2510 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2511 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2512 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2514 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2515 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2516 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2522 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2525 ModestMsgEditWindowPrivate *priv;
2526 gint new_font_index;
2527 ModestMsgEditWindow *window;
2530 window = MODEST_MSG_EDIT_WINDOW (userdata);
2531 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2532 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2534 if (gtk_check_menu_item_get_active (menu_item)) {
2537 label = gtk_bin_get_child (GTK_BIN (menu_item));
2539 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2541 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2542 GINT_TO_POINTER(new_font_index)))
2543 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2545 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2546 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2547 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2553 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2555 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2556 ModestWindowPrivate *parent_priv;
2557 ModestWindowMgr *mgr;
2558 gboolean is_fullscreen;
2559 GtkAction *fs_toggle_action;
2562 mgr = modest_runtime_get_window_mgr ();
2563 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2565 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2567 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2568 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2569 if (is_fullscreen != active)
2570 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2578 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2581 ModestMsgEditWindowPrivate *priv = NULL;
2582 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2584 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2585 if (!priv->update_caption_visibility)
2588 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2590 gtk_widget_show (priv->cc_caption);
2592 gtk_widget_hide (priv->cc_caption);
2594 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2598 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2601 ModestMsgEditWindowPrivate *priv = NULL;
2602 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2604 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2605 if (!priv->update_caption_visibility)
2608 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2610 gtk_widget_show (priv->bcc_caption);
2612 gtk_widget_hide (priv->bcc_caption);
2614 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2618 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2619 ModestRecptEditor *editor)
2621 ModestMsgEditWindowPrivate *priv;
2623 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2624 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2626 /* we check for low-mem; in that case, show a warning, and don't allow
2627 * for the addressbook
2629 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2632 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2634 if (editor == NULL) {
2635 GtkWidget *view_focus;
2636 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2638 /* This code should be kept in sync with ModestRecptEditor. The
2639 textview inside the recpt editor is the one that really gets the
2640 focus. As it's inside a scrolled window, and this one inside the
2641 hbox recpt editor inherits from, we'll need to go up in the
2642 hierarchy to know if the text view is part of the recpt editor
2643 or if it's a different text entry */
2645 if (gtk_widget_get_parent (view_focus)) {
2646 GtkWidget *first_parent;
2648 first_parent = gtk_widget_get_parent (view_focus);
2649 if (gtk_widget_get_parent (first_parent) &&
2650 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2651 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2656 editor = MODEST_RECPT_EDITOR (priv->to_field);
2660 modest_address_book_select_addresses (editor);
2665 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2667 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2669 modest_msg_edit_window_open_addressbook (window, NULL);
2673 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2674 gboolean show_toolbar)
2676 ModestWindowPrivate *parent_priv;
2677 const gchar *action_name;
2680 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2681 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2683 /* We can not just use the code of
2684 modest_msg_edit_window_setup_toolbar because it has a
2685 mixture of both initialization and creation code. */
2687 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2689 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2691 /* Update also the actions (to update the toggles in the
2692 menus), we have to do it manually because some other window
2693 of the same time could have changed it (remember that the
2694 toolbar fullscreen mode is shared by all the windows of the
2696 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2697 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2699 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2701 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2702 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2708 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2709 TnyHeaderFlags priority_flags)
2711 ModestMsgEditWindowPrivate *priv;
2712 ModestWindowPrivate *parent_priv;
2714 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2716 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2717 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2719 if (priv->priority_flags != priority_flags) {
2720 GtkAction *priority_action = NULL;
2722 priv->priority_flags = priority_flags;
2724 switch (priority_flags) {
2725 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2726 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), MODEST_HEADER_ICON_HIGH, GTK_ICON_SIZE_MENU);
2727 gtk_widget_show (priv->priority_icon);
2728 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2729 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2731 case TNY_HEADER_FLAG_LOW_PRIORITY:
2732 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "MODEST_HEADER_ICON_LOW", GTK_ICON_SIZE_MENU);
2733 gtk_widget_show (priv->priority_icon);
2734 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2735 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2738 gtk_widget_hide (priv->priority_icon);
2739 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2740 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2743 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2744 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2749 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2752 ModestMsgEditWindowPrivate *priv;
2753 ModestWindowPrivate *parent_priv;
2754 gint current_format;
2756 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2758 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2759 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2761 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2762 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2764 if (current_format != file_format) {
2765 switch (file_format) {
2766 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2767 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2768 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2770 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2774 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2775 response = gtk_dialog_run (GTK_DIALOG (dialog));
2776 gtk_widget_destroy (dialog);
2777 if (response == GTK_RESPONSE_OK) {
2778 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2780 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2781 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2786 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2787 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2788 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2793 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2796 ModestMsgEditWindowPrivate *priv;
2797 WPTextBufferFormat oldfmt, fmt;
2798 gint old_position = 0;
2802 GdkColor *color = NULL;
2803 gboolean bold, bold_set, italic, italic_set;
2804 gboolean underline, underline_set;
2805 gboolean strikethrough, strikethrough_set;
2806 gboolean position_set;
2807 gboolean font_size_set, font_set, color_set;
2810 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2811 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2813 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2814 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2815 GTK_WINDOW(dialog), GTK_WINDOW (window));
2817 /* First we get the currently selected font information */
2818 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2820 switch (oldfmt.text_position) {
2821 case TEXT_POSITION_NORMAL:
2824 case TEXT_POSITION_SUPERSCRIPT:
2832 g_object_set (G_OBJECT (dialog),
2833 "bold", oldfmt.bold != FALSE,
2834 "bold-set", !oldfmt.cs.bold,
2835 "underline", oldfmt.underline != FALSE,
2836 "underline-set", !oldfmt.cs.underline,
2837 "italic", oldfmt.italic != FALSE,
2838 "italic-set", !oldfmt.cs.italic,
2839 "strikethrough", oldfmt.strikethrough != FALSE,
2840 "strikethrough-set", !oldfmt.cs.strikethrough,
2841 "color", &oldfmt.color,
2842 "color-set", !oldfmt.cs.color,
2843 "size", wp_font_size[oldfmt.font_size],
2844 "size-set", !oldfmt.cs.font_size,
2845 "position", old_position,
2846 "position-set", !oldfmt.cs.text_position,
2847 "family", wp_get_font_name (oldfmt.font),
2848 "family-set", !oldfmt.cs.font,
2851 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2852 GTK_WINDOW (dialog), GTK_WINDOW (window));
2853 gtk_widget_show_all (dialog);
2854 priv->font_dialog = dialog;
2855 response = gtk_dialog_run (GTK_DIALOG (dialog));
2856 priv->font_dialog = NULL;
2857 if (response == GTK_RESPONSE_OK) {
2859 g_object_get( dialog,
2861 "bold-set", &bold_set,
2862 "underline", &underline,
2863 "underline-set", &underline_set,
2865 "italic-set", &italic_set,
2866 "strikethrough", &strikethrough,
2867 "strikethrough-set", &strikethrough_set,
2869 "color-set", &color_set,
2871 "size-set", &font_size_set,
2872 "family", &font_name,
2873 "family-set", &font_set,
2874 "position", &position,
2875 "position-set", &position_set,
2880 if (response == GTK_RESPONSE_OK) {
2881 memset(&fmt, 0, sizeof(fmt));
2887 fmt.italic = italic;
2888 fmt.cs.italic = TRUE;
2890 if (underline_set) {
2891 fmt.underline = underline;
2892 fmt.cs.underline = TRUE;
2894 if (strikethrough_set) {
2895 fmt.strikethrough = strikethrough;
2896 fmt.cs.strikethrough = TRUE;
2901 ? TEXT_POSITION_NORMAL
2902 : ( ( position == 1 )
2903 ? TEXT_POSITION_SUPERSCRIPT
2904 : TEXT_POSITION_SUBSCRIPT );
2905 fmt.cs.text_position = TRUE;
2906 fmt.font_size = oldfmt.font_size;
2910 fmt.cs.color = TRUE;
2913 fmt.font = wp_get_font_index(font_name,
2918 if (font_size_set) {
2919 fmt.cs.font_size = TRUE;
2920 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2922 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2923 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2925 gtk_widget_destroy (dialog);
2927 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2931 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2933 ModestMsgEditWindowPrivate *priv;
2935 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2936 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2938 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2940 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2941 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2945 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2947 ModestMsgEditWindowPrivate *priv;
2949 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2950 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2952 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2954 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2955 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2960 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2962 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2964 priv->can_undo = can_undo;
2968 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2970 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2972 priv->can_redo = can_redo;
2976 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2978 ModestMsgEditWindowPrivate *priv;
2979 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2980 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2982 return priv->can_undo;
2986 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2988 ModestMsgEditWindowPrivate *priv;
2989 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2990 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2992 return priv->can_redo;
2997 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3000 GtkTextIter match_start, match_end;
3002 if (image_id == NULL)
3005 gtk_text_buffer_get_start_iter (buffer, &iter);
3007 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3008 GSList *tags = gtk_text_iter_get_tags (&match_start);
3010 for (node = tags; node != NULL; node = g_slist_next (node)) {
3011 GtkTextTag *tag = (GtkTextTag *) node->data;
3012 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3013 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3014 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3016 offset = gtk_text_iter_get_offset (&match_start);
3017 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3018 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3022 gtk_text_iter_forward_char (&iter);
3027 message_is_empty (ModestMsgEditWindow *window)
3029 ModestMsgEditWindowPrivate *priv = NULL;
3031 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3032 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3034 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3035 * so we can ignore markup.
3037 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3040 count = gtk_text_buffer_get_char_count (buf);
3046 msg_body_focus (GtkWidget *focus,
3047 GdkEventFocus *event,
3051 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3052 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3053 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3058 recpt_field_changed (GtkTextBuffer *buffer,
3059 ModestMsgEditWindow *editor)
3061 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3062 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3066 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3068 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3069 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3073 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3076 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3077 GtkTextBuffer *buffer;
3079 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3080 gtk_text_buffer_set_modified (buffer, modified);
3081 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3082 gtk_text_buffer_set_modified (buffer, modified);
3083 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3084 gtk_text_buffer_set_modified (buffer, modified);
3085 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3089 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3091 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3092 const char *account_name;
3093 GtkTextBuffer *buffer;
3095 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3096 if (gtk_text_buffer_get_modified (buffer))
3098 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3099 if (gtk_text_buffer_get_modified (buffer))
3101 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3102 if (gtk_text_buffer_get_modified (buffer))
3104 if (gtk_text_buffer_get_modified (priv->text_buffer))
3106 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3107 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3118 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3120 ModestMsgEditWindowPrivate *priv = NULL;
3122 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3123 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3125 /* check if there's no recipient added */
3126 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3127 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3128 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3129 /* no recipient contents, then select contacts */
3130 modest_msg_edit_window_open_addressbook (window, NULL);
3134 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3135 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3138 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3139 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3142 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3143 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3147 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3148 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3149 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3156 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3157 ModestMsgEditWindow *window)
3159 modest_msg_edit_window_offer_attach_file (window);
3163 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3165 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3167 return priv->clipboard_text;
3171 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3173 ModestMsgEditWindow *window)
3175 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3176 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3178 if (!GTK_WIDGET_VISIBLE (window))
3181 g_object_ref (window);
3182 text = gtk_clipboard_wait_for_text (selection_clipboard);
3184 if (priv->clipboard_text != NULL) {
3185 g_free (priv->clipboard_text);
3187 priv->clipboard_text = text;
3189 if (GTK_WIDGET_VISIBLE (window)) {
3190 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3192 g_object_unref (window);
3195 static gboolean clipboard_owner_change_idle (gpointer userdata)
3197 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3198 ModestMsgEditWindowPrivate *priv;
3200 gdk_threads_enter ();
3201 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3202 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3204 priv->clipboard_owner_idle = 0;
3205 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3206 gdk_threads_leave ();
3212 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3214 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3215 if (priv->clipboard_owner_idle == 0) {
3216 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3221 subject_field_move_cursor (GtkEntry *entry,
3222 GtkMovementStep step,
3227 if (!GTK_WIDGET_VISIBLE (window))
3230 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3234 update_window_title (ModestMsgEditWindow *window)
3236 ModestMsgEditWindowPrivate *priv = NULL;
3237 const gchar *subject;
3239 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3240 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3241 if (subject == NULL || subject[0] == '\0')
3242 subject = _("mail_va_new_email");
3244 gtk_window_set_title (GTK_WINDOW (window), subject);
3249 subject_field_changed (GtkEditable *editable,
3250 ModestMsgEditWindow *window)
3252 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3253 update_window_title (window);
3254 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3255 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3256 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3260 subject_field_insert_text (GtkEditable *editable,
3262 gint new_text_length,
3264 ModestMsgEditWindow *window)
3266 GString *result = g_string_new ("");
3268 gint result_len = 0;
3269 const gchar *entry_text = NULL;
3272 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3273 old_length = g_utf8_strlen (entry_text, -1);
3275 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3276 gunichar c = g_utf8_get_char_validated (current, 8);
3277 /* Invalid unichar, stop */
3283 result = g_string_append_unichar (result, c);
3287 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3288 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3291 /* Prevent endless recursion */
3292 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3293 g_signal_emit_by_name (editable, "insert-text",
3294 (gpointer) result->str, (gpointer) result->len,
3295 (gpointer) position, (gpointer) window);
3296 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3300 if (result_len + old_length > 1000) {
3301 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3302 dgettext("hildon-common-strings",
3303 "ckdg_ib_maximum_characters_reached"));
3306 g_string_free (result, TRUE);
3310 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3313 ModestMsgEditWindowPrivate *priv = NULL;
3315 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3316 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3318 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3321 gtk_widget_show_all (priv->find_toolbar);
3322 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3324 gtk_widget_hide_all (priv->find_toolbar);
3325 gtk_widget_grab_focus (priv->msg_body);
3331 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3333 GtkTextIter *match_start,
3334 GtkTextIter *match_end)
3336 GtkTextIter end_iter;
3337 gchar *str_casefold;
3340 gchar *range_casefold;
3343 gboolean result = FALSE;
3350 gtk_text_iter_forward_to_end (&end_iter);
3352 str_casefold = g_utf8_casefold (str, -1);
3353 str_chars_n = strlen (str);
3355 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3356 range_casefold = g_utf8_casefold (range_text, -1);
3357 range_chars_n = strlen (range_casefold);
3359 if (range_chars_n < str_chars_n) {
3360 g_free (str_casefold);
3361 g_free (range_text);
3362 g_free (range_casefold);
3366 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3367 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3368 if (!g_utf8_collate (range_subtext, str_casefold)) {
3369 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3371 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3372 match_start, match_end, NULL);
3373 g_free (found_text);
3375 g_free (range_subtext);
3379 g_free (str_casefold);
3380 g_free (range_text);
3381 g_free (range_casefold);
3388 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3389 ModestMsgEditWindow *window)
3391 gchar *current_search = NULL;
3392 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3394 GtkTextIter selection_start, selection_end;
3395 GtkTextIter match_start, match_end;
3396 gboolean continue_search = FALSE;
3398 if (message_is_empty (window)) {
3399 g_free (priv->last_search);
3400 priv->last_search = NULL;
3401 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3405 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3406 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3407 g_free (current_search);
3408 g_free (priv->last_search);
3409 priv->last_search = NULL;
3410 /* Information banner about empty search */
3411 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3415 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3416 continue_search = TRUE;
3418 g_free (priv->last_search);
3419 priv->last_search = g_strdup (current_search);
3422 if (continue_search) {
3423 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3424 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3425 &match_start, &match_end);
3427 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3429 GtkTextIter buffer_start;
3430 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3431 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3432 &match_start, &match_end);
3434 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3437 /* Mark as selected the string found in search */
3439 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3440 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3441 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3443 g_free (priv->last_search);
3444 priv->last_search = NULL;
3446 g_free (current_search);
3450 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3451 ModestMsgEditWindow *window)
3453 GtkToggleAction *toggle;
3454 ModestWindowPrivate *parent_priv;
3455 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3457 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3458 gtk_toggle_action_set_active (toggle, FALSE);
3462 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3464 ModestMsgEditWindowPrivate *priv;
3466 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3471 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3474 ModestMsgEditWindowPrivate *priv;
3476 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3482 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3485 ModestMsgEditWindowPrivate *priv;
3486 TnyHeader *header = NULL;
3488 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3489 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3491 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3492 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3494 if (priv->draft_msg != NULL) {
3495 g_object_unref (priv->draft_msg);
3498 if (draft != NULL) {
3499 g_object_ref (draft);
3500 header = tny_msg_get_header (draft);
3501 if (priv->msg_uid) {
3502 g_free (priv->msg_uid);
3503 priv->msg_uid = NULL;
3505 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3506 if (GTK_WIDGET_REALIZED (window)) {
3507 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3508 gtk_widget_destroy (GTK_WIDGET (window));
3514 priv->draft_msg = draft;
3518 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3519 GtkTextIter *start, GtkTextIter *end,
3522 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3523 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3526 if (tag == NULL) return;
3527 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3528 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3529 replace_with_images (window, priv->images);
3534 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3537 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3539 g_return_if_fail (TNY_IS_MIME_PART (part));
3540 tny_list_prepend (priv->attachments, (GObject *) part);
3541 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3542 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3543 gtk_widget_show_all (priv->attachments_caption);
3544 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3548 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3550 ModestMsgEditWindowPrivate *priv;
3552 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3553 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3555 return priv->msg_uid;
3559 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3560 ModestMsgEditWindowWidgetType widget_type)
3562 ModestMsgEditWindowPrivate *priv;
3564 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3565 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3567 switch (widget_type) {
3568 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3569 return priv->msg_body;
3571 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3572 return priv->to_field;
3574 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3575 return priv->cc_field;
3577 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3578 return priv->bcc_field;
3580 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3581 return priv->subject_field;
3583 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3584 return priv->attachments_view;
3592 remove_tags (WPTextBuffer *buffer)
3594 GtkTextIter start, end;
3596 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3597 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3599 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3603 on_account_removed (TnyAccountStore *account_store,
3604 TnyAccount *account,
3607 /* Do nothing if it's a store account, because we use the
3608 transport to send the messages */
3609 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3610 const gchar *parent_acc = NULL;
3611 const gchar *our_acc = NULL;
3613 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3614 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3615 /* Close this window if I'm showing a message of the removed account */
3616 if (strcmp (parent_acc, our_acc) == 0)
3617 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3622 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3624 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3626 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3632 set_zoom_do_nothing (ModestWindow *window,
3638 get_zoom_do_nothing (ModestWindow *window)