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);
123 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
124 ModestRecptEditor *editor);
125 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
126 ModestMsgEditWindow *window);
128 /* ModestWindow methods implementation */
129 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
130 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
131 gboolean show_toolbar);
132 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
134 ModestMsgEditWindow *window);
135 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
136 static void subject_field_move_cursor (GtkEntry *entry,
137 GtkMovementStep step,
141 static void update_window_title (ModestMsgEditWindow *window);
144 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
145 ModestMsgEditWindow *window);
146 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
147 ModestMsgEditWindow *window);
148 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
150 GtkTextIter *match_start,
151 GtkTextIter *match_end);
153 static void remove_tags (WPTextBuffer *buffer);
155 static void on_account_removed (TnyAccountStore *account_store,
159 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
160 static void set_zoom_do_nothing (ModestWindow *window, gdouble zoom);
161 static gdouble get_zoom_do_nothing (ModestWindow *window);
163 static void init_window (ModestMsgEditWindow *obj);
165 gboolean scroll_drag_timeout (gpointer userdata);
166 static void correct_scroll (ModestMsgEditWindow *w);
167 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
168 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
169 ModestMsgEditWindow *userdata);
170 static void text_buffer_mark_set (GtkTextBuffer *buffer,
173 ModestMsgEditWindow *userdata);
175 static void DEBUG_BUFFER (WPTextBuffer *buffer)
179 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
181 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
182 while (!gtk_text_iter_is_end (&iter)) {
183 GString *output = g_string_new ("");
184 GSList *toggled_tags;
187 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
188 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
189 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
190 GtkTextTag *tag = (GtkTextTag *) node->data;
192 g_object_get (G_OBJECT (tag), "name", &name, NULL);
193 output = g_string_append (output, name);
194 g_string_append (output, " ");
196 output = g_string_append (output, "] OPENED [ ");
197 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
198 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
199 GtkTextTag *tag = (GtkTextTag *) node->data;
201 g_object_get (G_OBJECT (tag), "name", &name, NULL);
202 output = g_string_append (output, name);
203 g_string_append (output, " ");
205 output = g_string_append (output, "]\n");
206 g_message ("%s", output->str);
207 g_string_free (output, TRUE);
208 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
210 g_message ("END BUFFER");
215 /* static gboolean */
216 /* on_key_pressed (GtkWidget *self, */
217 /* GdkEventKey *event, */
218 /* gpointer user_data); */
220 /* list my signals */
227 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
228 struct _ModestMsgEditWindowPrivate {
231 GtkWidget *header_box;
233 ModestPairList *from_field_protos;
234 GtkWidget *from_field;
235 gchar *original_account_name;
239 GtkWidget *bcc_field;
240 GtkWidget *subject_field;
241 GtkWidget *attachments_view;
242 GtkWidget *priority_icon;
243 GtkWidget *add_attachment_button;
245 GtkWidget *cc_caption;
246 GtkWidget *bcc_caption;
247 gboolean update_caption_visibility;
248 GtkWidget *attachments_caption;
250 GtkTextBuffer *text_buffer;
252 GtkWidget *font_size_toolitem;
253 GtkWidget *font_face_toolitem;
254 GtkWidget *font_color_button;
255 GSList *font_items_group;
256 GtkWidget *font_tool_button_label;
257 GSList *size_items_group;
258 GtkWidget *size_tool_button_label;
260 GtkWidget *find_toolbar;
263 GtkWidget *font_dialog;
266 guint scroll_drag_timeout_id;
270 TnyList *attachments;
275 TnyHeaderFlags priority_flags;
277 gboolean can_undo, can_redo;
278 gulong clipboard_change_handler_id;
279 gulong default_clipboard_change_handler_id;
280 gulong account_removed_handler_id;
281 guint clipboard_owner_idle;
282 gchar *clipboard_text;
291 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
292 MODEST_TYPE_MSG_EDIT_WINDOW, \
293 ModestMsgEditWindowPrivate))
295 static GtkWindowClass *parent_class = NULL;
297 /* uncomment the following if you have defined any signals */
298 /* static guint signals[LAST_SIGNAL] = {0}; */
301 modest_msg_edit_window_get_type (void)
303 static GType my_type = 0;
305 static const GTypeInfo my_info = {
306 sizeof(ModestMsgEditWindowClass),
307 NULL, /* base init */
308 NULL, /* base finalize */
309 (GClassInitFunc) modest_msg_edit_window_class_init,
310 NULL, /* class finalize */
311 NULL, /* class data */
312 sizeof(ModestMsgEditWindow),
314 (GInstanceInitFunc) modest_msg_edit_window_init,
317 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
318 "ModestMsgEditWindow",
326 save_state (ModestWindow *self)
328 modest_widget_memory_save (modest_runtime_get_conf(),
329 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
334 restore_settings (ModestMsgEditWindow *self)
336 ModestConf *conf = NULL;
338 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
340 conf = modest_runtime_get_conf ();
342 /* Dim at start clipboard actions */
343 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
344 gtk_action_set_sensitive (action, FALSE);
345 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
346 gtk_action_set_sensitive (action, FALSE);
347 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
348 gtk_action_set_sensitive (action, FALSE);
350 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
355 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
357 GObjectClass *gobject_class;
358 ModestWindowClass *modest_window_class;
359 gobject_class = (GObjectClass*) klass;
360 modest_window_class = (ModestWindowClass*) klass;
362 parent_class = g_type_class_peek_parent (klass);
363 gobject_class->finalize = modest_msg_edit_window_finalize;
365 modest_window_class->set_zoom_func = set_zoom_do_nothing;
366 modest_window_class->get_zoom_func = get_zoom_do_nothing;
367 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
368 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
369 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
370 modest_window_class->save_state_func = save_state;
371 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
373 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
377 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
379 ModestMsgEditWindowPrivate *priv;
380 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
382 priv->msg_body = NULL;
384 priv->from_field = NULL;
385 priv->to_field = NULL;
386 priv->cc_field = NULL;
387 priv->bcc_field = NULL;
388 priv->subject_field = NULL;
389 priv->attachments = TNY_LIST (tny_simple_list_new ());
390 priv->images = TNY_LIST (tny_simple_list_new ());
391 priv->images_size = 0;
392 priv->images_count = 0;
395 priv->cc_caption = NULL;
396 priv->bcc_caption = NULL;
397 priv->update_caption_visibility = FALSE;
399 priv->priority_flags = 0;
401 priv->find_toolbar = NULL;
402 priv->last_search = NULL;
404 priv->draft_msg = NULL;
405 priv->outbox_msg = NULL;
406 priv->msg_uid = NULL;
408 priv->can_undo = FALSE;
409 priv->can_redo = FALSE;
410 priv->clipboard_change_handler_id = 0;
411 priv->default_clipboard_change_handler_id = 0;
412 priv->account_removed_handler_id = 0;
413 priv->clipboard_owner_idle = 0;
414 priv->clipboard_text = NULL;
417 priv->scroll_drag_timeout_id = 0;
418 priv->last_upper = 0.0;
420 priv->font_dialog = NULL;
422 if (!is_wp_text_buffer_started) {
423 is_wp_text_buffer_started = TRUE;
424 wp_text_buffer_library_init ();
429 hildon_program_add_window (hildon_program_get_instance(),
435 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
437 static ModestPairList*
438 get_transports (void)
440 GSList *transports = NULL;
442 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
443 GSList *accounts = modest_account_mgr_account_names (account_mgr,
444 TRUE /* only enabled accounts. */);
446 GSList *cursor = accounts;
448 gchar *account_name = cursor->data;
449 gchar *from_string = NULL;
451 from_string = modest_account_mgr_get_from_string (account_mgr,
455 if (from_string && account_name) {
456 gchar *name = account_name;
457 ModestPair *pair = modest_pair_new ((gpointer) name,
458 (gpointer) from_string , TRUE);
459 transports = g_slist_prepend (transports, pair);
462 cursor = cursor->next;
464 g_slist_free (accounts); /* only free the accounts, not the elements,
465 * because they are used in the pairlist */
469 static void window_focus (GtkWindow *window,
473 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
477 scroll_drag_timeout (gpointer userdata)
479 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
480 ModestMsgEditWindowPrivate *priv;
482 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
484 correct_scroll_without_drag_check (win, TRUE);
486 priv->scroll_drag_timeout_id = 0;
492 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
494 ModestMsgEditWindowPrivate *priv;
497 GdkRectangle rectangle;
501 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
503 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
506 insert = gtk_text_buffer_get_insert (priv->text_buffer);
507 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
509 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
510 offset = priv->msg_body->allocation.y;
512 new_value = (offset + rectangle.y);
514 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (priv->pannable), -1, new_value);
518 correct_scroll (ModestMsgEditWindow *w)
520 ModestMsgEditWindowPrivate *priv;
522 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
523 if (gtk_grab_get_current () == priv->msg_body) {
524 if (priv->scroll_drag_timeout_id == 0) {
525 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
531 correct_scroll_without_drag_check (w, TRUE);
535 text_buffer_end_user_action (GtkTextBuffer *buffer,
536 ModestMsgEditWindow *userdata)
539 correct_scroll (userdata);
543 text_buffer_mark_set (GtkTextBuffer *buffer,
546 ModestMsgEditWindow *userdata)
548 gtk_text_buffer_begin_user_action (buffer);
549 gtk_text_buffer_end_user_action (buffer);
553 cut_clipboard_check (GtkTextView *text_view,
556 GtkTextBuffer *buffer;
558 buffer = gtk_text_view_get_buffer (text_view);
559 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
560 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
565 copy_clipboard_check (GtkTextView *text_view,
568 GtkTextBuffer *buffer;
570 buffer = gtk_text_view_get_buffer (text_view);
571 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
572 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
577 attachment_deleted (ModestAttachmentsView *attachments_view,
580 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
585 connect_signals (ModestMsgEditWindow *obj)
587 ModestMsgEditWindowPrivate *priv;
589 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
591 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
592 G_CALLBACK (text_buffer_refresh_attributes), obj);
593 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
594 G_CALLBACK (text_buffer_can_undo), obj);
595 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
596 G_CALLBACK (text_buffer_can_redo), obj);
597 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
598 G_CALLBACK (body_changed), obj);
599 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
600 G_CALLBACK (body_changed), obj);
601 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
602 G_CALLBACK (text_buffer_end_user_action), obj);
603 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
604 G_CALLBACK (text_buffer_mark_set), obj);
605 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
606 G_CALLBACK (text_buffer_apply_tag), obj);
607 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
608 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
609 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
610 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
611 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
612 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
614 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
615 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
617 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
618 G_CALLBACK (msg_body_focus), obj);
619 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
620 G_CALLBACK (msg_body_focus), obj);
621 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
622 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
623 "changed", G_CALLBACK (recpt_field_changed), obj);
624 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
625 "changed", G_CALLBACK (recpt_field_changed), obj);
626 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
627 "changed", G_CALLBACK (recpt_field_changed), obj);
628 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
629 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
630 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
632 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
633 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
635 priv->clipboard_change_handler_id =
636 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
637 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
638 priv->default_clipboard_change_handler_id =
639 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
640 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
642 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
643 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
644 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
648 init_window (ModestMsgEditWindow *obj)
650 GtkWidget *to_caption, *subject_caption;
651 GtkWidget *main_vbox;
652 ModestMsgEditWindowPrivate *priv;
653 GtkActionGroup *action_group;
654 ModestWindowPrivate *parent_priv;
655 GdkPixbuf *window_icon = NULL;
656 GError *error = NULL;
658 GtkSizeGroup *title_size_group;
659 GtkSizeGroup *value_size_group;
660 GtkWidget *subject_box;
661 GtkWidget *attachment_icon;
662 GtkWidget *window_box;
663 #if (GTK_MINOR_VERSION >= 10)
664 GdkAtom deserialize_type;
667 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
668 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
670 parent_priv->ui_manager = gtk_ui_manager_new();
671 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
672 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
674 /* Add common actions */
675 gtk_action_group_add_actions (action_group,
676 modest_msg_edit_action_entries,
677 G_N_ELEMENTS (modest_msg_edit_action_entries),
679 gtk_action_group_add_toggle_actions (action_group,
680 modest_msg_edit_toggle_action_entries,
681 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
683 gtk_action_group_add_radio_actions (action_group,
684 modest_msg_edit_alignment_radio_action_entries,
685 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
687 G_CALLBACK (modest_ui_actions_on_change_justify),
689 gtk_action_group_add_radio_actions (action_group,
690 modest_msg_edit_priority_action_entries,
691 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
693 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
695 gtk_action_group_add_radio_actions (action_group,
696 modest_msg_edit_file_format_action_entries,
697 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
698 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
699 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
701 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
702 g_object_unref (action_group);
704 /* Load the UI definition */
705 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
708 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
709 g_clear_error (&error);
712 /* Add accelerators */
713 gtk_window_add_accel_group (GTK_WINDOW (obj),
714 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
716 parent_priv->menubar = NULL;
718 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
719 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
721 /* Note: This ModestPairList* must exist for as long as the picker
722 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
723 * so it can't know how to manage its memory. */
724 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
725 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
727 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
728 _("mail_va_from"), priv->from_field);
730 priv->to_field = modest_recpt_editor_new ();
731 priv->cc_field = modest_recpt_editor_new ();
732 priv->bcc_field = modest_recpt_editor_new ();
733 subject_box = gtk_hbox_new (FALSE, 0);
734 priv->priority_icon = gtk_image_new ();
735 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
736 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
737 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
738 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
739 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
740 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
741 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
742 priv->add_attachment_button = gtk_button_new ();
743 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
744 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
745 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
746 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 0.5);
747 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
748 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
749 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
750 priv->attachments_view = modest_attachments_view_new (NULL);
752 priv->header_box = gtk_vbox_new (FALSE, 0);
754 to_caption = modest_maemo_utils_create_captioned_with_size_type
755 (title_size_group, value_size_group,
756 _("mail_va_to"), priv->to_field,
757 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
758 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
759 (title_size_group, value_size_group,
760 _("mail_va_cc"), priv->cc_field,
761 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
762 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
763 (title_size_group, value_size_group,
764 _("mail_va_hotfix1"), priv->bcc_field,
765 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
766 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
767 _("mail_va_subject"), subject_box);
768 priv->attachments_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
769 _("mail_va_attachment"),
770 priv->attachments_view);
771 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
772 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
773 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
774 g_object_unref (title_size_group);
775 g_object_unref (value_size_group);
777 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
778 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
779 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
780 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
781 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
782 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
783 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
786 priv->msg_body = wp_text_view_new ();
787 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
788 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
789 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
790 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
791 #if (GTK_MINOR_VERSION >= 10)
792 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
793 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
795 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
796 deserialize_type, TRUE);
798 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
800 priv->find_toolbar = hildon_find_toolbar_new (NULL);
801 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
803 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
805 priv->pannable = hildon_pannable_area_new ();
807 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
809 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
810 priv->frame = gtk_frame_new (NULL);
811 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
813 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), main_vbox);
814 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
816 window_box = gtk_vbox_new (FALSE, 0);
817 gtk_container_add (GTK_CONTAINER(obj), window_box);
819 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
821 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
823 /* Set window icon */
824 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
826 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
827 g_object_unref (window_icon);
832 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
834 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
836 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
837 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
838 priv->clipboard_change_handler_id))
839 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
840 priv->clipboard_change_handler_id);
841 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
842 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
843 priv->default_clipboard_change_handler_id))
844 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
845 priv->default_clipboard_change_handler_id);
847 if (priv->account_removed_handler_id &&
848 g_signal_handler_is_connected (modest_runtime_get_account_store (),
849 priv->account_removed_handler_id))
850 g_signal_handler_disconnect(modest_runtime_get_account_store (),
851 priv->account_removed_handler_id);
855 modest_msg_edit_window_finalize (GObject *obj)
857 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
859 /* Sanity check: shouldn't be needed, the window mgr should
860 call this function before */
861 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
863 if (priv->font_dialog != NULL) {
864 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
867 if (priv->clipboard_text != NULL) {
868 g_free (priv->clipboard_text);
869 priv->clipboard_text = NULL;
872 if (priv->draft_msg != NULL) {
873 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
874 if (TNY_IS_HEADER (header)) {
875 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
876 modest_window_mgr_unregister_header (mgr, header);
878 g_object_unref (priv->draft_msg);
879 priv->draft_msg = NULL;
881 if (priv->outbox_msg != NULL) {
882 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
883 if (TNY_IS_HEADER (header)) {
884 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
885 modest_window_mgr_unregister_header (mgr, header);
887 g_object_unref (priv->outbox_msg);
888 priv->outbox_msg = NULL;
890 if (priv->scroll_drag_timeout_id > 0) {
891 g_source_remove (priv->scroll_drag_timeout_id);
892 priv->scroll_drag_timeout_id = 0;
894 if (priv->clipboard_owner_idle > 0) {
895 g_source_remove (priv->clipboard_owner_idle);
896 priv->clipboard_owner_idle = 0;
898 if (priv->original_account_name)
899 g_free (priv->original_account_name);
900 g_free (priv->msg_uid);
901 g_free (priv->last_search);
902 g_slist_free (priv->font_items_group);
903 g_slist_free (priv->size_items_group);
904 g_object_unref (priv->attachments);
905 g_object_unref (priv->images);
907 /* This had to stay alive for as long as the picker that used it: */
908 modest_pair_list_free (priv->from_field_protos);
910 G_OBJECT_CLASS(parent_class)->finalize (obj);
914 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
916 GdkPixbufLoader *loader;
922 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
924 if (loader == NULL) {
930 tny_stream_reset (TNY_STREAM (stream));
931 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
932 GError *error = NULL;
933 unsigned char read_buffer[128];
935 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
937 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
939 g_error_free (error);
944 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
946 g_object_ref (pixbuf);
947 gdk_pixbuf_loader_close (loader, NULL);
948 g_object_unref (loader);
953 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
954 GdkPixbuf *new_pixbuf;
956 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
957 gdk_pixbuf_get_width (pixbuf);
958 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
959 g_object_unref (pixbuf);
970 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
972 ModestMsgEditWindowPrivate *priv;
975 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
977 for (iter = tny_list_create_iterator (attachments);
978 !tny_iterator_is_done (iter);
979 tny_iterator_next (iter)) {
980 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
981 const gchar *cid = tny_mime_part_get_content_id (part);
982 const gchar *mime_type = tny_mime_part_get_content_type (part);
983 if ((cid != NULL)&&(mime_type != NULL)) {
985 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
986 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
989 g_object_unref (stream);
991 if (pixbuf != NULL) {
992 priv->images_count ++;
993 priv->images_size += stream_size;
994 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
995 g_object_unref (pixbuf);
998 g_object_unref (part);
1000 g_object_unref (iter);
1004 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1006 TnyMimePart *parent = NULL;
1007 const gchar *content_type = NULL;
1008 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1010 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1012 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1013 parent = g_object_ref (msg);
1014 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1015 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1018 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1019 iter = tny_list_create_iterator (parts);
1020 while (!tny_iterator_is_done (iter)) {
1022 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1023 content_type = tny_mime_part_get_content_type (part);
1024 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1028 g_object_unref (part);
1030 tny_iterator_next (iter);
1032 g_object_unref (iter);
1033 g_object_unref (parts);
1036 if (parent != NULL) {
1037 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1040 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1041 iter = tny_list_create_iterator (parts);
1042 while (!tny_iterator_is_done (iter)) {
1044 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1045 content_type = tny_mime_part_get_content_type (part);
1046 if (content_type && g_str_has_prefix (content_type, "image/")) {
1047 tny_list_prepend (priv->images, (GObject *) part);
1049 g_object_unref (part);
1050 tny_iterator_next (iter);
1052 g_object_unref (iter);
1053 g_object_unref (parts);
1054 g_object_unref (parent);
1059 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1062 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1064 for (iter = tny_list_create_iterator (attachments) ;
1065 !tny_iterator_is_done (iter);
1066 tny_iterator_next (iter)) {
1067 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1068 const gchar *cid = tny_mime_part_get_content_id (part);
1070 char *invalid = NULL;
1071 gint int_cid = strtol (cid, &invalid, 10);
1072 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1073 priv->next_cid = int_cid + 1;
1076 g_object_unref (part);
1078 g_object_unref (iter);
1082 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1085 gchar *to, *cc, *bcc, *subject;
1087 ModestMsgEditWindowPrivate *priv;
1088 ModestWindowPrivate *parent_priv;
1090 TnyHeaderFlags priority_flags;
1091 TnyFolder *msg_folder;
1092 gboolean is_html = FALSE;
1094 gboolean field_view_set;
1096 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1097 g_return_if_fail (TNY_IS_MSG (msg));
1099 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1100 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1102 header = tny_msg_get_header (msg);
1103 to = tny_header_dup_to (header);
1104 cc = tny_header_dup_cc (header);
1105 bcc = tny_header_dup_bcc (header);
1106 subject = tny_header_dup_subject (header);
1107 priority_flags = tny_header_get_priority (header);
1110 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1112 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
1113 field_view_set = TRUE;
1115 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1116 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1117 gtk_widget_show (priv->cc_caption);
1118 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1119 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1120 gtk_widget_hide (priv->cc_caption);
1121 field_view_set = FALSE;
1124 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), field_view_set);
1126 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
1127 field_view_set = TRUE;
1129 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1130 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1131 gtk_widget_show (priv->bcc_caption);
1132 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1133 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1134 gtk_widget_hide (priv->bcc_caption);
1135 field_view_set = FALSE;
1138 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), field_view_set);
1142 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1143 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1146 update_window_title (self);
1148 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1149 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1151 if ((body == NULL)||(body[0] == '\0')) {
1153 body = modest_text_utils_convert_to_html ("");
1156 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1157 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1160 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1163 /* Add attachments to the view */
1164 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1165 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1166 if (tny_list_get_length (priv->attachments) == 0) {
1167 gtk_widget_hide (priv->attachments_caption);
1169 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1170 gtk_widget_show_all (priv->attachments_caption);
1172 get_related_images (self, msg);
1173 update_next_cid (self, priv->attachments);
1174 update_next_cid (self, priv->images);
1175 replace_with_images (self, priv->images);
1177 if (preserve_is_rich && !is_html) {
1178 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1179 /* Get the default format required from configuration */
1180 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1181 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1184 /* Set the default focus depending on having already a To: field or not */
1185 if ((!to)||(*to == '\0')) {
1186 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1188 gtk_widget_grab_focus (priv->msg_body);
1191 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1193 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1194 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1196 modest_msg_edit_window_set_modified (self, FALSE);
1198 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1199 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1200 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1201 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1203 if (priv->msg_uid) {
1204 g_free (priv->msg_uid);
1205 priv->msg_uid = NULL;
1208 /* we should set a reference to the incoming message if it is a draft */
1209 msg_folder = tny_msg_get_folder (msg);
1211 if (modest_tny_folder_is_local_folder (msg_folder)) {
1212 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1213 if (type == TNY_FOLDER_TYPE_INVALID)
1214 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1216 if (type == TNY_FOLDER_TYPE_DRAFTS)
1217 priv->draft_msg = g_object_ref(msg);
1218 if (type == TNY_FOLDER_TYPE_OUTBOX)
1219 priv->outbox_msg = g_object_ref(msg);
1220 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1222 g_object_unref (msg_folder);
1232 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1235 GList *item_children, *node;
1236 GtkWidget *bin_child;
1238 bin_child = gtk_bin_get_child (GTK_BIN(item));
1240 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1242 for (node = item_children; node != NULL; node = g_list_next (node)) {
1243 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1244 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1247 g_list_free (item_children);
1251 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1254 GList *item_children, *node;
1256 box = gtk_bin_get_child (GTK_BIN (item));
1257 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1258 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1260 for (node = item_children; node != NULL; node = g_list_next (node)) {
1261 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1262 if (GTK_IS_TOGGLE_BUTTON (node->data))
1263 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1264 else if (GTK_IS_BUTTON (node->data))
1265 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1267 g_list_free (item_children);
1272 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1274 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1275 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1276 GtkWidget *placeholder;
1277 GtkWidget *tool_item;
1282 GtkWidget *sizes_menu;
1283 GtkWidget *fonts_menu;
1284 GSList *radio_group = NULL;
1285 GSList *node = NULL;
1289 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1290 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1292 /* Font color placeholder */
1293 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1294 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1297 tool_item = GTK_WIDGET (gtk_tool_item_new ());
1298 priv->font_color_button = hildon_color_button_new ();
1299 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1300 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1301 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
1302 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1303 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1304 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1305 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1307 G_CALLBACK (modest_msg_edit_window_color_button_change),
1310 /* Font size and face placeholder */
1311 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1312 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1314 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1315 priv->size_tool_button_label = gtk_label_new (NULL);
1316 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1317 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1318 size_text,"</span>", NULL);
1319 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1321 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1322 sizes_menu = gtk_menu_new ();
1323 priv->size_items_group = NULL;
1325 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1326 GtkWidget *size_menu_item;
1328 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1329 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1330 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1331 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1332 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1333 gtk_widget_show (size_menu_item);
1335 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1339 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1340 GtkWidget *item = (GtkWidget *) node->data;
1341 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1345 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1346 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1347 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1348 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1349 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1350 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1351 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1352 priv->font_size_toolitem = tool_item;
1355 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1356 priv->font_tool_button_label = gtk_label_new (NULL);
1357 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1358 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1360 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1361 fonts_menu = gtk_menu_new ();
1362 priv->font_items_group = NULL;
1364 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1365 GtkWidget *font_menu_item;
1366 GtkWidget *child_label;
1368 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1369 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1370 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1371 wp_get_font_name (font_index), "</span>", NULL);
1372 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1375 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1376 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1377 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1378 gtk_widget_show (font_menu_item);
1380 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1383 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1384 GtkWidget *item = (GtkWidget *) node->data;
1385 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1388 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1389 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1390 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1391 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1392 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1393 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1394 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1395 priv->font_face_toolitem = tool_item;
1397 /* Set expand and homogeneous for remaining items */
1398 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1399 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1400 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1401 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1402 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1403 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1404 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1405 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1406 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1408 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1409 will not show the tool items added to the placeholders) */
1410 gtk_widget_show_all (parent_priv->toolbar);
1412 /* Set the no show all *after* showing all items. We do not
1413 want the toolbar to be shown with a show all because it
1414 could go agains the gconf setting regarding showing or not
1415 the toolbar of the editor window */
1416 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1422 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1425 ModestWindowPrivate *parent_priv;
1426 ModestMsgEditWindowPrivate *priv;
1427 ModestDimmingRulesGroup *menu_rules_group = NULL;
1428 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1429 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1430 ModestWindowMgr *mgr = NULL;
1432 g_return_val_if_fail (msg, NULL);
1433 g_return_val_if_fail (account_name, NULL);
1435 mgr = modest_runtime_get_window_mgr ();
1437 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1439 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1440 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1442 /* Menubar. Update the state of some toggles */
1443 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1444 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1445 priv->from_field_protos = get_transports ();
1446 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1447 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1448 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1450 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1451 hildon_touch_selector_get_current_text
1452 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1453 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1454 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1457 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1459 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1461 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1463 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1465 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1466 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1467 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1468 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1469 /* Add common dimming rules */
1470 modest_dimming_rules_group_add_rules (menu_rules_group,
1471 modest_msg_edit_window_menu_dimming_entries,
1472 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1473 MODEST_WINDOW (obj));
1474 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1475 modest_msg_edit_window_toolbar_dimming_entries,
1476 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1477 MODEST_WINDOW (obj));
1478 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1479 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1480 MODEST_WINDOW (obj));
1481 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1482 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1483 MODEST_WINDOW (obj));
1484 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1485 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1486 MODEST_WINDOW (obj));
1487 /* Insert dimming rules group for this window */
1488 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1489 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1490 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1491 /* Checks the dimming rules */
1492 g_object_unref (menu_rules_group);
1493 g_object_unref (toolbar_rules_group);
1494 g_object_unref (clipboard_rules_group);
1495 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1497 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1499 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1500 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1501 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1502 priv->update_caption_visibility = TRUE;
1504 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1506 /* Track account-removed signal, this window should be closed
1507 in the case we're creating a mail associated to the account
1509 priv->account_removed_handler_id =
1510 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1512 G_CALLBACK(on_account_removed),
1515 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1517 return (ModestWindow*) obj;
1521 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1523 GString **string_buffer = (GString **) user_data;
1525 *string_buffer = g_string_append (*string_buffer, buffer);
1531 * @result: A new string which should be freed with g_free().
1534 get_formatted_data (ModestMsgEditWindow *edit_window)
1536 ModestMsgEditWindowPrivate *priv;
1537 GString *string_buffer = g_string_new ("");
1539 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1541 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1543 modest_text_utils_hyperlinkify (string_buffer);
1545 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1547 return g_string_free (string_buffer, FALSE);
1552 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1555 const gchar *account_name;
1556 ModestMsgEditWindowPrivate *priv;
1557 TnyIterator *att_iter;
1559 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1561 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1563 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1564 g_return_val_if_fail (account_name, NULL);
1567 /* don't free these (except from) */
1568 data = g_slice_new0 (MsgData);
1569 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1571 data->account_name = g_strdup (account_name);
1572 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1573 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1574 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1575 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1576 if (priv->draft_msg) {
1577 data->draft_msg = g_object_ref (priv->draft_msg);
1578 } else if (priv->outbox_msg) {
1579 data->draft_msg = g_object_ref (priv->outbox_msg);
1581 data->draft_msg = NULL;
1584 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1586 gtk_text_buffer_get_bounds (buf, &b, &e);
1587 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1589 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1590 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1592 data->html_body = NULL;
1594 /* deep-copy the data */
1595 att_iter = tny_list_create_iterator (priv->attachments);
1596 data->attachments = NULL;
1597 while (!tny_iterator_is_done (att_iter)) {
1598 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1599 if (!(TNY_IS_MIME_PART(part))) {
1600 g_warning ("strange data in attachment list");
1601 g_object_unref (part);
1602 tny_iterator_next (att_iter);
1605 data->attachments = g_list_append (data->attachments,
1607 tny_iterator_next (att_iter);
1609 g_object_unref (att_iter);
1611 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1612 att_iter = tny_list_create_iterator (priv->images);
1613 data->images = NULL;
1614 while (!tny_iterator_is_done (att_iter)) {
1615 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1617 if (!(TNY_IS_MIME_PART(part))) {
1618 g_warning ("strange data in attachment list");
1619 g_object_unref (part);
1620 tny_iterator_next (att_iter);
1623 cid = tny_mime_part_get_content_id (part);
1625 gchar *image_tag_id;
1626 GtkTextTag *image_tag;
1628 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1629 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1630 g_free (image_tag_id);
1632 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1634 ((gtk_text_iter_has_tag (&iter, image_tag))||
1635 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1636 data->images = g_list_append (data->images,
1637 g_object_ref (part));
1639 g_object_unref (part);
1640 tny_iterator_next (att_iter);
1642 g_object_unref (att_iter);
1644 data->priority_flags = priv->priority_flags;
1651 unref_gobject (GObject *obj, gpointer data)
1653 if (!G_IS_OBJECT(obj))
1655 g_object_unref (obj);
1659 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1662 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1670 g_free (data->from);
1671 g_free (data->subject);
1672 g_free (data->plain_body);
1673 g_free (data->html_body);
1674 g_free (data->account_name);
1676 if (data->draft_msg != NULL) {
1677 g_object_unref (data->draft_msg);
1678 data->draft_msg = NULL;
1681 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1682 g_list_free (data->attachments);
1683 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1684 g_list_free (data->images);
1686 g_slice_free (MsgData, data);
1690 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1692 guint64 *parts_size)
1694 ModestMsgEditWindowPrivate *priv;
1696 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1698 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1700 /* TODO: add images */
1701 *parts_size += priv->images_size;
1702 *parts_count += priv->images_count;
1707 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1710 ModestMsgEditWindowPrivate *priv = NULL;
1711 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1713 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1715 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1717 return MODEST_MSG_EDIT_FORMAT_HTML;
1719 return MODEST_MSG_EDIT_FORMAT_TEXT;
1723 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1724 ModestMsgEditFormat format)
1726 ModestMsgEditWindowPrivate *priv;
1728 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1729 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1732 case MODEST_MSG_EDIT_FORMAT_HTML:
1733 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1735 case MODEST_MSG_EDIT_FORMAT_TEXT:
1736 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1739 g_return_if_reached ();
1743 ModestMsgEditFormatState *
1744 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1746 ModestMsgEditFormatState *format_state = NULL;
1747 ModestMsgEditWindowPrivate *priv;
1748 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1750 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1751 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1753 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1755 format_state = g_new0 (ModestMsgEditFormatState, 1);
1756 format_state->bold = buffer_format->bold&0x1;
1757 format_state->italics = buffer_format->italic&0x1;
1758 format_state->bullet = buffer_format->bullet&0x1;
1759 format_state->color = buffer_format->color;
1760 format_state->font_size = buffer_format->font_size;
1761 format_state->font_family = wp_get_font_name (buffer_format->font);
1762 format_state->justification = buffer_format->justification;
1763 g_free (buffer_format);
1765 return format_state;
1770 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1771 const ModestMsgEditFormatState *format_state)
1773 ModestMsgEditWindowPrivate *priv;
1774 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1775 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1776 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1777 g_return_if_fail (format_state != NULL);
1779 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1780 gtk_widget_grab_focus (priv->msg_body);
1781 buffer_format->bold = (format_state->bold != FALSE);
1782 buffer_format->italic = (format_state->italics != FALSE);
1783 buffer_format->color = format_state->color;
1784 buffer_format->font_size = format_state->font_size;
1785 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1786 buffer_format->justification = format_state->justification;
1787 buffer_format->bullet = format_state->bullet;
1789 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1791 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1792 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1793 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1794 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1795 buffer_format->cs.font = (buffer_format->font != current_format->font);
1796 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1797 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1799 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1800 if (buffer_format->cs.bold) {
1801 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1802 GINT_TO_POINTER (buffer_format->bold&0x1));
1804 if (buffer_format->cs.italic) {
1805 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1806 GINT_TO_POINTER (buffer_format->italic&0x1));
1808 if (buffer_format->cs.color) {
1809 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1810 GINT_TO_POINTER (&(buffer_format->color)));
1812 if (buffer_format->cs.font_size) {
1813 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1814 GINT_TO_POINTER (buffer_format->font_size));
1816 if (buffer_format->cs.justification) {
1817 switch (buffer_format->justification) {
1818 case GTK_JUSTIFY_LEFT:
1819 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1820 GINT_TO_POINTER(TRUE));
1822 case GTK_JUSTIFY_CENTER:
1823 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1824 GINT_TO_POINTER(TRUE));
1826 case GTK_JUSTIFY_RIGHT:
1827 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1828 GINT_TO_POINTER(TRUE));
1835 if (buffer_format->cs.font) {
1836 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1837 GINT_TO_POINTER (buffer_format->font));
1839 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1840 if (buffer_format->cs.bullet) {
1841 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1842 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1844 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1846 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1848 g_free (buffer_format);
1849 g_free (current_format);
1851 /* Check dimming rules */
1852 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1853 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1857 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1859 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1861 ModestWindowPrivate *parent_priv;
1862 ModestMsgEditWindowPrivate *priv;
1863 GtkWidget *new_size_menuitem;
1864 GtkWidget *new_font_menuitem;
1866 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1867 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1869 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1870 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1871 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1872 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1874 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1875 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1876 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1879 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1881 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1882 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1884 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1885 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1887 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1888 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1891 switch (buffer_format->justification)
1893 case GTK_JUSTIFY_LEFT:
1894 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1896 case GTK_JUSTIFY_CENTER:
1897 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1899 case GTK_JUSTIFY_RIGHT:
1900 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1907 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1909 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1910 G_CALLBACK (modest_msg_edit_window_color_button_change),
1912 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1913 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1914 G_CALLBACK (modest_msg_edit_window_color_button_change),
1917 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1918 buffer_format->font_size))->data);
1919 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1923 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1924 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1925 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1927 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1928 G_CALLBACK (modest_msg_edit_window_size_change),
1930 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1931 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1932 G_CALLBACK (modest_msg_edit_window_size_change),
1936 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1937 buffer_format->font))->data);
1938 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1942 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1943 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1944 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1946 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1947 G_CALLBACK (modest_msg_edit_window_font_change),
1949 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1950 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1951 G_CALLBACK (modest_msg_edit_window_font_change),
1955 g_free (buffer_format);
1959 #ifdef MODEST_HILDON_VERSION_0
1961 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1964 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1965 ModestMsgEditWindowPrivate *priv;
1966 GtkWidget *dialog = NULL;
1968 GdkColor *new_color = NULL;
1970 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1971 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1973 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1974 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1975 g_free (buffer_format);
1977 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
1978 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1979 if (new_color != NULL) {
1980 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1981 (gpointer) new_color);
1984 gtk_widget_destroy (dialog);
1989 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1992 ModestMsgEditWindowPrivate *priv;
1993 GtkWidget *dialog = NULL;
1995 GdkColor *old_color = NULL;
1996 const GdkColor *new_color = NULL;
1998 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1999 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2001 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2002 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2004 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2005 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2006 if (new_color != NULL)
2007 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2009 gtk_widget_destroy (dialog);
2015 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2018 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2019 ModestMsgEditWindowPrivate *priv;
2020 GtkWidget *dialog = NULL;
2022 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2023 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2025 dialog = hildon_color_chooser_new ();
2026 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2027 g_free (buffer_format);
2029 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2031 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2032 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2035 gtk_widget_destroy (dialog);
2040 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2043 ModestMsgEditWindowPrivate *priv;
2044 GtkWidget *dialog = NULL;
2045 GdkColor *old_color = NULL;
2047 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2048 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2050 dialog = hildon_color_chooser_new ();
2051 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2053 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2055 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2056 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2058 gtk_widget_destroy (dialog);
2061 #endif /*!MODEST_HILDON_VERSION_0*/
2066 create_stream_for_uri (const gchar* uri)
2071 TnyStream *result = NULL;
2073 GnomeVFSHandle *handle = NULL;
2074 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2075 if (test == GNOME_VFS_OK) {
2076 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2077 /* Streams over OBEX (Bluetooth) are not seekable but
2078 * we expect them to be (we might need to read them
2079 * several times). So if this is a Bluetooth URI just
2080 * read the whole file into memory (this is not a fast
2081 * protocol so we can assume that these files are not
2082 * going to be very big) */
2083 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2084 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2085 TnyStream *memstream = tny_camel_mem_stream_new ();
2086 tny_stream_write_to_stream (vfssstream, memstream);
2087 g_object_unref (vfssstream);
2090 result = vfssstream;
2098 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2101 ModestMsgEditWindowPrivate *priv;
2102 GtkWidget *dialog = NULL;
2104 GSList *uris = NULL;
2105 GSList *uri_node = NULL;
2107 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2109 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2110 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2111 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2113 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2115 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2116 GTK_WINDOW (dialog), GTK_WINDOW (window));
2118 response = gtk_dialog_run (GTK_DIALOG (dialog));
2120 case GTK_RESPONSE_OK:
2121 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2126 gtk_widget_destroy (dialog);
2128 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2130 GnomeVFSHandle *handle = NULL;
2131 GnomeVFSResult result;
2132 GtkTextIter position;
2133 GtkTextMark *insert_mark;
2135 uri = (const gchar *) uri_node->data;
2136 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2137 if (result == GNOME_VFS_OK) {
2139 GnomeVFSFileInfo *info;
2140 gchar *filename, *basename, *escaped_filename;
2141 TnyMimePart *mime_part;
2143 const gchar *mime_type = NULL;
2144 GnomeVFSURI *vfs_uri;
2145 guint64 stream_size;
2147 gnome_vfs_close (handle);
2148 vfs_uri = gnome_vfs_uri_new (uri);
2150 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2151 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2152 g_free (escaped_filename);
2153 gnome_vfs_uri_unref (vfs_uri);
2154 info = gnome_vfs_file_info_new ();
2156 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2157 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2159 mime_type = gnome_vfs_file_info_get_mime_type (info);
2161 mime_part = tny_platform_factory_new_mime_part
2162 (modest_runtime_get_platform_factory ());
2164 TnyStream *stream = create_stream_for_uri (uri);
2166 if (stream == NULL) {
2168 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2170 g_object_unref (mime_part);
2171 gnome_vfs_file_info_unref (info);
2175 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2177 content_id = g_strdup_printf ("%d", priv->next_cid);
2178 tny_mime_part_set_content_id (mime_part, content_id);
2179 g_free (content_id);
2182 basename = g_path_get_basename (filename);
2183 tny_mime_part_set_filename (mime_part, basename);
2186 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2188 if (pixbuf != NULL) {
2189 priv->images_size += stream_size;
2190 priv->images_count ++;
2191 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2192 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2193 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2194 g_object_unref (pixbuf);
2197 tny_list_prepend (priv->images, (GObject *) mime_part);
2198 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2200 g_object_unref (mime_part);
2201 gnome_vfs_file_info_unref (info);
2210 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2212 GtkWidget *dialog = NULL;
2214 GSList *uris = NULL;
2216 GnomeVFSFileSize total_size, allowed_size;
2217 ModestMsgEditWindowPrivate *priv;
2221 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2223 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2225 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2228 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2229 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2230 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2231 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), GTK_WINDOW (window));
2233 response = gtk_dialog_run (GTK_DIALOG (dialog));
2235 case GTK_RESPONSE_OK:
2236 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2241 gtk_widget_destroy (dialog);
2243 /* allowed size is the maximum size - what's already there */
2244 modest_attachments_view_get_sizes (
2245 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2246 &att_num, &att_size);
2247 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2250 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2252 const gchar *uri = (const gchar *) uri_node->data;
2254 total_size += modest_msg_edit_window_attach_file_one
2255 (window, uri, allowed_size);
2257 if (total_size > allowed_size) {
2258 g_warning ("%s: total size: %u",
2259 __FUNCTION__, (unsigned int)total_size);
2263 allowed_size -= total_size;
2267 g_slist_foreach (uris, (GFunc) g_free, NULL);
2268 g_slist_free (uris);
2273 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2275 GnomeVFSFileSize allowed_size)
2278 GnomeVFSHandle *handle = NULL;
2279 ModestMsgEditWindowPrivate *priv;
2280 GnomeVFSResult result;
2281 GnomeVFSFileSize size = 0;
2282 g_return_val_if_fail (window, 0);
2283 g_return_val_if_fail (uri, 0);
2285 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2287 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2288 if (result == GNOME_VFS_OK) {
2289 TnyMimePart *mime_part;
2291 const gchar *mime_type = NULL;
2293 gchar *escaped_filename;
2296 GnomeVFSFileInfo *info;
2297 GnomeVFSURI *vfs_uri;
2299 gnome_vfs_close (handle);
2300 vfs_uri = gnome_vfs_uri_new (uri);
2303 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2304 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2305 g_free (escaped_filename);
2306 gnome_vfs_uri_unref (vfs_uri);
2308 info = gnome_vfs_file_info_new ();
2310 if (gnome_vfs_get_file_info (uri,
2312 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2314 mime_type = gnome_vfs_file_info_get_mime_type (info);
2315 mime_part = tny_platform_factory_new_mime_part
2316 (modest_runtime_get_platform_factory ());
2318 /* try to get the attachment's size; this may fail for weird
2319 * file systems, like obex, upnp... */
2320 if (allowed_size != 0 &&
2321 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2323 if (size > allowed_size) {
2324 modest_platform_information_banner (NULL, NULL,
2325 dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2329 g_warning ("%s: could not get attachment size", __FUNCTION__);
2331 stream = create_stream_for_uri (uri);
2333 if (stream == NULL) {
2335 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2337 g_object_unref (mime_part);
2338 gnome_vfs_file_info_unref (info);
2342 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2343 g_object_unref (stream);
2345 content_id = g_strdup_printf ("%d", priv->next_cid);
2346 tny_mime_part_set_content_id (mime_part, content_id);
2347 g_free (content_id);
2350 basename = g_path_get_basename (filename);
2351 tny_mime_part_set_filename (mime_part, basename);
2354 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2355 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2357 info->size == 0, info->size);
2358 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2359 gtk_widget_show_all (priv->attachments_caption);
2360 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2362 g_object_unref (mime_part);
2363 gnome_vfs_file_info_unref (info);
2370 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2373 ModestMsgEditWindowPrivate *priv;
2376 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2377 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2379 if (att_list == NULL) {
2380 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2382 g_object_ref (att_list);
2385 if (tny_list_get_length (att_list) == 0) {
2386 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2388 gboolean dialog_response;
2389 gchar *message = NULL;
2390 gchar *filename = NULL;
2392 if (tny_list_get_length (att_list) == 1) {
2394 iter = tny_list_create_iterator (att_list);
2395 part = (TnyMimePart *) tny_iterator_get_current (iter);
2396 g_object_unref (iter);
2397 if (TNY_IS_MSG (part)) {
2398 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2400 filename = tny_header_dup_subject (header);
2401 g_object_unref (header);
2403 if (filename == NULL) {
2404 filename = g_strdup (_("mail_va_no_subject"));
2407 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2409 g_object_unref (part);
2411 filename = g_strdup ("");
2413 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2414 tny_list_get_length (att_list)), filename);
2417 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2420 if (dialog_response != GTK_RESPONSE_OK) {
2421 g_object_unref (att_list);
2424 hildon_banner_show_information (NULL, NULL, _("mcen_me_inbox_remove_attachments"));
2426 for (iter = tny_list_create_iterator (att_list);
2427 !tny_iterator_is_done (iter);
2428 tny_iterator_next (iter)) {
2429 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2430 const gchar *att_id;
2431 tny_list_remove (priv->attachments, (GObject *) mime_part);
2433 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2435 if (tny_list_get_length (priv->attachments) == 0)
2436 gtk_widget_hide (priv->attachments_caption);
2437 att_id = tny_mime_part_get_content_id (mime_part);
2439 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2441 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2442 g_object_unref (mime_part);
2444 g_object_unref (iter);
2447 g_object_unref (att_list);
2449 /* if the last attachment has been removed, focus the Subject: field */
2450 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2451 gtk_widget_grab_focus (priv->subject_field);
2455 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2458 ModestMsgEditWindowPrivate *priv;
2459 GdkColor *new_color;
2460 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2462 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2463 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2466 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2468 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2470 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2472 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2477 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2480 ModestMsgEditWindowPrivate *priv;
2481 gint new_size_index;
2482 ModestMsgEditWindow *window;
2485 window = MODEST_MSG_EDIT_WINDOW (userdata);
2486 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2487 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2489 if (gtk_check_menu_item_get_active (menu_item)) {
2491 WPTextBufferFormat format;
2493 memset (&format, 0, sizeof (format));
2494 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2496 label = gtk_bin_get_child (GTK_BIN (menu_item));
2498 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2499 format.cs.font_size = TRUE;
2500 format.cs.text_position = TRUE;
2501 format.cs.font = TRUE;
2502 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2503 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2505 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2506 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2507 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2509 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2510 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2511 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2517 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2520 ModestMsgEditWindowPrivate *priv;
2521 gint new_font_index;
2522 ModestMsgEditWindow *window;
2525 window = MODEST_MSG_EDIT_WINDOW (userdata);
2526 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2527 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2529 if (gtk_check_menu_item_get_active (menu_item)) {
2532 label = gtk_bin_get_child (GTK_BIN (menu_item));
2534 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2536 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2537 GINT_TO_POINTER(new_font_index)))
2538 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2540 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2541 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2542 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2548 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2551 ModestMsgEditWindowPrivate *priv = NULL;
2552 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2554 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2555 if (!priv->update_caption_visibility)
2558 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2560 gtk_widget_show (priv->cc_caption);
2562 gtk_widget_hide (priv->cc_caption);
2564 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2568 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2571 ModestMsgEditWindowPrivate *priv = NULL;
2572 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2574 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2575 if (!priv->update_caption_visibility)
2578 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2580 gtk_widget_show (priv->bcc_caption);
2582 gtk_widget_hide (priv->bcc_caption);
2584 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2588 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2589 ModestRecptEditor *editor)
2591 ModestMsgEditWindowPrivate *priv;
2593 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2594 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2596 /* we check for low-mem; in that case, show a warning, and don't allow
2597 * for the addressbook
2599 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2602 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2604 if (editor == NULL) {
2605 GtkWidget *view_focus;
2606 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2608 /* This code should be kept in sync with ModestRecptEditor. The
2609 textview inside the recpt editor is the one that really gets the
2610 focus. As it's inside a scrolled window, and this one inside the
2611 hbox recpt editor inherits from, we'll need to go up in the
2612 hierarchy to know if the text view is part of the recpt editor
2613 or if it's a different text entry */
2615 if (gtk_widget_get_parent (view_focus)) {
2616 GtkWidget *first_parent;
2618 first_parent = gtk_widget_get_parent (view_focus);
2619 if (gtk_widget_get_parent (first_parent) &&
2620 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2621 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2626 editor = MODEST_RECPT_EDITOR (priv->to_field);
2630 modest_address_book_select_addresses (editor);
2635 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2637 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2639 modest_msg_edit_window_open_addressbook (window, NULL);
2643 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2644 gboolean show_toolbar)
2646 ModestWindowPrivate *parent_priv;
2648 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2649 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2651 /* We can not just use the code of
2652 modest_msg_edit_window_setup_toolbar because it has a
2653 mixture of both initialization and creation code. */
2655 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2657 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2661 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2662 TnyHeaderFlags priority_flags)
2664 ModestMsgEditWindowPrivate *priv;
2665 ModestWindowPrivate *parent_priv;
2667 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2669 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2670 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2672 if (priv->priority_flags != priority_flags) {
2673 GtkAction *priority_action = NULL;
2675 priv->priority_flags = priority_flags;
2677 switch (priority_flags) {
2678 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2679 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2680 MODEST_HEADER_ICON_HIGH,
2681 HILDON_ICON_SIZE_XSMALL);
2682 gtk_widget_show (priv->priority_icon);
2683 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2684 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2686 case TNY_HEADER_FLAG_LOW_PRIORITY:
2687 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2688 MODEST_HEADER_ICON_LOW,
2689 HILDON_ICON_SIZE_XSMALL);
2690 gtk_widget_show (priv->priority_icon);
2691 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2692 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2695 gtk_widget_hide (priv->priority_icon);
2696 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2697 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2700 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2701 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2706 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2709 ModestMsgEditWindowPrivate *priv;
2710 ModestWindowPrivate *parent_priv;
2711 gint current_format;
2713 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2715 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2716 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2718 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2719 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2721 if (current_format != file_format) {
2722 switch (file_format) {
2723 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2724 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2725 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2727 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2731 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2732 response = gtk_dialog_run (GTK_DIALOG (dialog));
2733 gtk_widget_destroy (dialog);
2734 if (response == GTK_RESPONSE_OK) {
2735 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2737 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2738 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2743 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2744 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2745 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2750 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2753 ModestMsgEditWindowPrivate *priv;
2754 WPTextBufferFormat oldfmt, fmt;
2755 gint old_position = 0;
2759 GdkColor *color = NULL;
2760 gboolean bold, bold_set, italic, italic_set;
2761 gboolean underline, underline_set;
2762 gboolean strikethrough, strikethrough_set;
2763 gboolean position_set;
2764 gboolean font_size_set, font_set, color_set;
2767 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2768 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2770 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2771 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2772 GTK_WINDOW(dialog), GTK_WINDOW (window));
2774 /* First we get the currently selected font information */
2775 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2777 switch (oldfmt.text_position) {
2778 case TEXT_POSITION_NORMAL:
2781 case TEXT_POSITION_SUPERSCRIPT:
2789 g_object_set (G_OBJECT (dialog),
2790 "bold", oldfmt.bold != FALSE,
2791 "bold-set", !oldfmt.cs.bold,
2792 "underline", oldfmt.underline != FALSE,
2793 "underline-set", !oldfmt.cs.underline,
2794 "italic", oldfmt.italic != FALSE,
2795 "italic-set", !oldfmt.cs.italic,
2796 "strikethrough", oldfmt.strikethrough != FALSE,
2797 "strikethrough-set", !oldfmt.cs.strikethrough,
2798 "color", &oldfmt.color,
2799 "color-set", !oldfmt.cs.color,
2800 "size", wp_font_size[oldfmt.font_size],
2801 "size-set", !oldfmt.cs.font_size,
2802 "position", old_position,
2803 "position-set", !oldfmt.cs.text_position,
2804 "family", wp_get_font_name (oldfmt.font),
2805 "family-set", !oldfmt.cs.font,
2808 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2809 GTK_WINDOW (dialog), GTK_WINDOW (window));
2810 gtk_widget_show_all (dialog);
2811 priv->font_dialog = dialog;
2812 response = gtk_dialog_run (GTK_DIALOG (dialog));
2813 priv->font_dialog = NULL;
2814 if (response == GTK_RESPONSE_OK) {
2816 g_object_get( dialog,
2818 "bold-set", &bold_set,
2819 "underline", &underline,
2820 "underline-set", &underline_set,
2822 "italic-set", &italic_set,
2823 "strikethrough", &strikethrough,
2824 "strikethrough-set", &strikethrough_set,
2826 "color-set", &color_set,
2828 "size-set", &font_size_set,
2829 "family", &font_name,
2830 "family-set", &font_set,
2831 "position", &position,
2832 "position-set", &position_set,
2837 if (response == GTK_RESPONSE_OK) {
2838 memset(&fmt, 0, sizeof(fmt));
2844 fmt.italic = italic;
2845 fmt.cs.italic = TRUE;
2847 if (underline_set) {
2848 fmt.underline = underline;
2849 fmt.cs.underline = TRUE;
2851 if (strikethrough_set) {
2852 fmt.strikethrough = strikethrough;
2853 fmt.cs.strikethrough = TRUE;
2858 ? TEXT_POSITION_NORMAL
2859 : ( ( position == 1 )
2860 ? TEXT_POSITION_SUPERSCRIPT
2861 : TEXT_POSITION_SUBSCRIPT );
2862 fmt.cs.text_position = TRUE;
2863 fmt.font_size = oldfmt.font_size;
2867 fmt.cs.color = TRUE;
2870 fmt.font = wp_get_font_index(font_name,
2875 if (font_size_set) {
2876 fmt.cs.font_size = TRUE;
2877 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2879 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2880 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2882 gtk_widget_destroy (dialog);
2884 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2888 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2890 ModestMsgEditWindowPrivate *priv;
2892 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2893 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2895 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2897 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2898 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2902 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2904 ModestMsgEditWindowPrivate *priv;
2906 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2907 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2909 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2911 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2912 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2917 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2919 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2921 priv->can_undo = can_undo;
2925 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2927 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2929 priv->can_redo = can_redo;
2933 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2935 ModestMsgEditWindowPrivate *priv;
2936 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2937 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2939 return priv->can_undo;
2943 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2945 ModestMsgEditWindowPrivate *priv;
2946 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2947 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2949 return priv->can_redo;
2954 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2957 GtkTextIter match_start, match_end;
2959 if (image_id == NULL)
2962 gtk_text_buffer_get_start_iter (buffer, &iter);
2964 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2965 GSList *tags = gtk_text_iter_get_tags (&match_start);
2967 for (node = tags; node != NULL; node = g_slist_next (node)) {
2968 GtkTextTag *tag = (GtkTextTag *) node->data;
2969 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2970 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2971 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2973 offset = gtk_text_iter_get_offset (&match_start);
2974 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2975 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2979 gtk_text_iter_forward_char (&iter);
2984 message_is_empty (ModestMsgEditWindow *window)
2986 ModestMsgEditWindowPrivate *priv = NULL;
2988 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2989 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2991 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
2992 * so we can ignore markup.
2994 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
2997 count = gtk_text_buffer_get_char_count (buf);
3003 msg_body_focus (GtkWidget *focus,
3004 GdkEventFocus *event,
3008 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3009 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3010 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3015 recpt_field_changed (GtkTextBuffer *buffer,
3016 ModestMsgEditWindow *editor)
3018 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3019 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3023 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3025 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3026 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3030 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3033 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3034 GtkTextBuffer *buffer;
3036 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3037 gtk_text_buffer_set_modified (buffer, modified);
3038 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3039 gtk_text_buffer_set_modified (buffer, modified);
3040 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3041 gtk_text_buffer_set_modified (buffer, modified);
3042 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3046 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3048 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3049 const char *account_name;
3050 GtkTextBuffer *buffer;
3052 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3053 if (gtk_text_buffer_get_modified (buffer))
3055 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3056 if (gtk_text_buffer_get_modified (buffer))
3058 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3059 if (gtk_text_buffer_get_modified (buffer))
3061 if (gtk_text_buffer_get_modified (priv->text_buffer))
3063 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3064 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3075 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3077 ModestMsgEditWindowPrivate *priv = NULL;
3079 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3080 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3082 /* check if there's no recipient added */
3083 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3084 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3085 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3086 /* no recipient contents, then select contacts */
3087 modest_msg_edit_window_open_addressbook (window, NULL);
3091 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3092 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3095 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3096 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3099 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3100 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3104 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3105 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3106 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3113 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3114 ModestMsgEditWindow *window)
3116 modest_msg_edit_window_offer_attach_file (window);
3120 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3122 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3124 return priv->clipboard_text;
3128 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3130 ModestMsgEditWindow *window)
3132 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3133 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3135 if (!GTK_WIDGET_VISIBLE (window))
3138 g_object_ref (window);
3139 text = gtk_clipboard_wait_for_text (selection_clipboard);
3141 if (priv->clipboard_text != NULL) {
3142 g_free (priv->clipboard_text);
3144 priv->clipboard_text = text;
3146 if (GTK_WIDGET_VISIBLE (window)) {
3147 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3149 g_object_unref (window);
3152 static gboolean clipboard_owner_change_idle (gpointer userdata)
3154 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3155 ModestMsgEditWindowPrivate *priv;
3157 gdk_threads_enter ();
3158 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3159 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3161 priv->clipboard_owner_idle = 0;
3162 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3163 gdk_threads_leave ();
3169 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3171 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3172 if (priv->clipboard_owner_idle == 0) {
3173 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3178 subject_field_move_cursor (GtkEntry *entry,
3179 GtkMovementStep step,
3184 if (!GTK_WIDGET_VISIBLE (window))
3187 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3191 update_window_title (ModestMsgEditWindow *window)
3193 ModestMsgEditWindowPrivate *priv = NULL;
3194 const gchar *subject;
3196 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3197 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3198 if (subject == NULL || subject[0] == '\0')
3199 subject = _("mail_va_new_email");
3201 gtk_window_set_title (GTK_WINDOW (window), subject);
3206 subject_field_changed (GtkEditable *editable,
3207 ModestMsgEditWindow *window)
3209 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3210 update_window_title (window);
3211 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3212 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3213 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3217 subject_field_insert_text (GtkEditable *editable,
3219 gint new_text_length,
3221 ModestMsgEditWindow *window)
3223 GString *result = g_string_new ("");
3225 gint result_len = 0;
3226 const gchar *entry_text = NULL;
3229 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3230 old_length = g_utf8_strlen (entry_text, -1);
3232 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3233 gunichar c = g_utf8_get_char_validated (current, 8);
3234 /* Invalid unichar, stop */
3240 result = g_string_append_unichar (result, c);
3244 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3245 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3248 /* Prevent endless recursion */
3249 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3250 g_signal_emit_by_name (editable, "insert-text",
3251 (gpointer) result->str, (gpointer) result->len,
3252 (gpointer) position, (gpointer) window);
3253 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3257 if (result_len + old_length > 1000) {
3258 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3259 dgettext("hildon-common-strings",
3260 "ckdg_ib_maximum_characters_reached"));
3263 g_string_free (result, TRUE);
3267 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3270 ModestMsgEditWindowPrivate *priv = NULL;
3272 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3273 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3275 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3278 gtk_widget_show_all (priv->find_toolbar);
3279 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3281 gtk_widget_hide_all (priv->find_toolbar);
3282 gtk_widget_grab_focus (priv->msg_body);
3288 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3290 GtkTextIter *match_start,
3291 GtkTextIter *match_end)
3293 GtkTextIter end_iter;
3294 gchar *str_casefold;
3297 gchar *range_casefold;
3300 gboolean result = FALSE;
3307 gtk_text_iter_forward_to_end (&end_iter);
3309 str_casefold = g_utf8_casefold (str, -1);
3310 str_chars_n = strlen (str);
3312 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3313 range_casefold = g_utf8_casefold (range_text, -1);
3314 range_chars_n = strlen (range_casefold);
3316 if (range_chars_n < str_chars_n) {
3317 g_free (str_casefold);
3318 g_free (range_text);
3319 g_free (range_casefold);
3323 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3324 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3325 if (!g_utf8_collate (range_subtext, str_casefold)) {
3326 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3328 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3329 match_start, match_end, NULL);
3330 g_free (found_text);
3332 g_free (range_subtext);
3336 g_free (str_casefold);
3337 g_free (range_text);
3338 g_free (range_casefold);
3345 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3346 ModestMsgEditWindow *window)
3348 gchar *current_search = NULL;
3349 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3351 GtkTextIter selection_start, selection_end;
3352 GtkTextIter match_start, match_end;
3353 gboolean continue_search = FALSE;
3355 if (message_is_empty (window)) {
3356 g_free (priv->last_search);
3357 priv->last_search = NULL;
3358 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3362 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3363 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3364 g_free (current_search);
3365 g_free (priv->last_search);
3366 priv->last_search = NULL;
3367 /* Information banner about empty search */
3368 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3372 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3373 continue_search = TRUE;
3375 g_free (priv->last_search);
3376 priv->last_search = g_strdup (current_search);
3379 if (continue_search) {
3380 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3381 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3382 &match_start, &match_end);
3384 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3386 GtkTextIter buffer_start;
3387 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3388 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3389 &match_start, &match_end);
3391 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3394 /* Mark as selected the string found in search */
3396 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3397 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3398 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3400 g_free (priv->last_search);
3401 priv->last_search = NULL;
3403 g_free (current_search);
3407 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3408 ModestMsgEditWindow *window)
3410 GtkToggleAction *toggle;
3411 ModestWindowPrivate *parent_priv;
3412 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3414 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3415 gtk_toggle_action_set_active (toggle, FALSE);
3419 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3421 ModestMsgEditWindowPrivate *priv;
3423 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3428 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3431 ModestMsgEditWindowPrivate *priv;
3433 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3439 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3442 ModestMsgEditWindowPrivate *priv;
3443 TnyHeader *header = NULL;
3445 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3446 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3448 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3449 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3451 if (priv->draft_msg != NULL) {
3452 g_object_unref (priv->draft_msg);
3455 if (draft != NULL) {
3456 g_object_ref (draft);
3457 header = tny_msg_get_header (draft);
3458 if (priv->msg_uid) {
3459 g_free (priv->msg_uid);
3460 priv->msg_uid = NULL;
3462 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3463 if (GTK_WIDGET_REALIZED (window)) {
3464 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3465 gtk_widget_destroy (GTK_WIDGET (window));
3471 priv->draft_msg = draft;
3475 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3476 GtkTextIter *start, GtkTextIter *end,
3479 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3480 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3483 if (tag == NULL) return;
3484 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3485 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3486 replace_with_images (window, priv->images);
3491 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3494 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3496 g_return_if_fail (TNY_IS_MIME_PART (part));
3497 tny_list_prepend (priv->attachments, (GObject *) part);
3498 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3499 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3500 gtk_widget_show_all (priv->attachments_caption);
3501 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3505 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3507 ModestMsgEditWindowPrivate *priv;
3509 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3510 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3512 return priv->msg_uid;
3516 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3517 ModestMsgEditWindowWidgetType widget_type)
3519 ModestMsgEditWindowPrivate *priv;
3521 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3522 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3524 switch (widget_type) {
3525 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3526 return priv->msg_body;
3528 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3529 return priv->to_field;
3531 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3532 return priv->cc_field;
3534 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3535 return priv->bcc_field;
3537 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3538 return priv->subject_field;
3540 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3541 return priv->attachments_view;
3549 remove_tags (WPTextBuffer *buffer)
3551 GtkTextIter start, end;
3553 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3554 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3556 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3560 on_account_removed (TnyAccountStore *account_store,
3561 TnyAccount *account,
3564 /* Do nothing if it's a store account, because we use the
3565 transport to send the messages */
3566 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3567 const gchar *parent_acc = NULL;
3568 const gchar *our_acc = NULL;
3570 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3571 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3572 /* Close this window if I'm showing a message of the removed account */
3573 if (strcmp (parent_acc, our_acc) == 0)
3574 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3579 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3581 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3583 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3589 set_zoom_do_nothing (ModestWindow *window,
3595 get_zoom_do_nothing (ModestWindow *window)