1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
42 #include <modest-account-mgr.h>
43 #include <modest-account-mgr-helpers.h>
45 #include <widgets/modest-msg-edit-window.h>
46 #include <modest-selector-picker.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <wptextview.h>
65 #include <wptextbuffer.h>
66 #include "modest-scroll-area.h"
67 #include "modest-msg-edit-window-ui-dimming.h"
69 #include "modest-hildon-includes.h"
70 #ifdef MODEST_HAVE_HILDON0_WIDGETS
71 #include <hildon-widgets/hildon-color-chooser.h>
73 #include "widgets/modest-msg-edit-window-ui.h"
74 #ifdef MODEST_HAVE_HILDON0_WIDGETS
75 #include <libgnomevfs/gnome-vfs-mime-utils.h>
77 #include <libgnomevfs/gnome-vfs-mime.h>
79 #include <modest-utils.h>
80 #include "modest-maemo-utils.h"
81 #include <modest-ui-constants.h>
84 #define DEFAULT_FONT_SIZE 3
85 #define DEFAULT_FONT 2
86 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
87 #define DEFAULT_MAIN_VBOX_SPACING 6
88 #define SUBJECT_MAX_LENGTH 1000
89 #define IMAGE_MAX_WIDTH 560
90 #define DEFAULT_FONT_SCALE 1.5
92 static gboolean is_wp_text_buffer_started = FALSE;
94 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
95 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
96 static void modest_msg_edit_window_finalize (GObject *obj);
98 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
99 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
100 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
102 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
103 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
104 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
105 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
106 GtkTextIter *start, GtkTextIter *end,
108 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
109 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
110 static void subject_field_insert_text (GtkEditable *editable,
112 gint new_text_length,
114 ModestMsgEditWindow *window);
115 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
117 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
119 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
121 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
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);
174 static void vadj_changed (GtkAdjustment *adj,
175 ModestMsgEditWindow *window);
177 static void DEBUG_BUFFER (WPTextBuffer *buffer)
181 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
183 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
184 while (!gtk_text_iter_is_end (&iter)) {
185 GString *output = g_string_new ("");
186 GSList *toggled_tags;
189 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
190 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
191 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
192 GtkTextTag *tag = (GtkTextTag *) node->data;
194 g_object_get (G_OBJECT (tag), "name", &name, NULL);
195 output = g_string_append (output, name);
196 g_string_append (output, " ");
198 output = g_string_append (output, "] OPENED [ ");
199 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
200 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
201 GtkTextTag *tag = (GtkTextTag *) node->data;
203 g_object_get (G_OBJECT (tag), "name", &name, NULL);
204 output = g_string_append (output, name);
205 g_string_append (output, " ");
207 output = g_string_append (output, "]\n");
208 g_message ("%s", output->str);
209 g_string_free (output, TRUE);
210 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
212 g_message ("END BUFFER");
217 /* static gboolean */
218 /* on_key_pressed (GtkWidget *self, */
219 /* GdkEventKey *event, */
220 /* gpointer user_data); */
222 /* list my signals */
229 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
230 struct _ModestMsgEditWindowPrivate {
233 GtkWidget *header_box;
235 ModestPairList *from_field_protos;
236 GtkWidget *from_field;
237 gchar *original_account_name;
241 GtkWidget *bcc_field;
242 GtkWidget *subject_field;
243 GtkWidget *attachments_view;
244 GtkWidget *priority_icon;
245 GtkWidget *add_attachment_button;
247 GtkWidget *cc_caption;
248 GtkWidget *bcc_caption;
249 gboolean update_caption_visibility;
250 GtkWidget *attachments_caption;
252 GtkTextBuffer *text_buffer;
254 GtkWidget *font_size_toolitem;
255 GtkWidget *font_face_toolitem;
256 GtkWidget *font_color_button;
257 GSList *font_items_group;
258 GtkWidget *font_tool_button_label;
259 GSList *size_items_group;
260 GtkWidget *size_tool_button_label;
262 GtkWidget *find_toolbar;
265 GtkWidget *font_dialog;
268 guint scroll_drag_timeout_id;
272 TnyList *attachments;
277 TnyHeaderFlags priority_flags;
279 gboolean can_undo, can_redo;
280 gulong clipboard_change_handler_id;
281 gulong default_clipboard_change_handler_id;
282 gulong account_removed_handler_id;
283 guint clipboard_owner_idle;
284 gchar *clipboard_text;
293 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
294 MODEST_TYPE_MSG_EDIT_WINDOW, \
295 ModestMsgEditWindowPrivate))
297 static GtkWindowClass *parent_class = NULL;
299 /* uncomment the following if you have defined any signals */
300 /* static guint signals[LAST_SIGNAL] = {0}; */
303 modest_msg_edit_window_get_type (void)
305 static GType my_type = 0;
307 static const GTypeInfo my_info = {
308 sizeof(ModestMsgEditWindowClass),
309 NULL, /* base init */
310 NULL, /* base finalize */
311 (GClassInitFunc) modest_msg_edit_window_class_init,
312 NULL, /* class finalize */
313 NULL, /* class data */
314 sizeof(ModestMsgEditWindow),
316 (GInstanceInitFunc) modest_msg_edit_window_init,
319 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
320 "ModestMsgEditWindow",
328 save_state (ModestWindow *self)
330 modest_widget_memory_save (modest_runtime_get_conf(),
331 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
336 restore_settings (ModestMsgEditWindow *self)
338 ModestConf *conf = NULL;
340 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
342 conf = modest_runtime_get_conf ();
344 /* Dim at start clipboard actions */
345 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
346 gtk_action_set_sensitive (action, FALSE);
347 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
348 gtk_action_set_sensitive (action, FALSE);
349 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
350 gtk_action_set_sensitive (action, FALSE);
352 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
357 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
359 GObjectClass *gobject_class;
360 ModestWindowClass *modest_window_class;
361 gobject_class = (GObjectClass*) klass;
362 modest_window_class = (ModestWindowClass*) klass;
364 parent_class = g_type_class_peek_parent (klass);
365 gobject_class->finalize = modest_msg_edit_window_finalize;
367 modest_window_class->set_zoom_func = set_zoom_do_nothing;
368 modest_window_class->get_zoom_func = get_zoom_do_nothing;
369 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
370 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
371 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
372 modest_window_class->save_state_func = save_state;
373 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
375 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
379 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
381 ModestMsgEditWindowPrivate *priv;
382 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
384 priv->msg_body = NULL;
386 priv->from_field = NULL;
387 priv->to_field = NULL;
388 priv->cc_field = NULL;
389 priv->bcc_field = NULL;
390 priv->subject_field = NULL;
391 priv->attachments = TNY_LIST (tny_simple_list_new ());
392 priv->images = TNY_LIST (tny_simple_list_new ());
393 priv->images_size = 0;
394 priv->images_count = 0;
397 priv->cc_caption = NULL;
398 priv->bcc_caption = NULL;
399 priv->update_caption_visibility = FALSE;
401 priv->priority_flags = 0;
403 priv->find_toolbar = NULL;
404 priv->last_search = NULL;
406 priv->draft_msg = NULL;
407 priv->outbox_msg = NULL;
408 priv->msg_uid = NULL;
410 priv->can_undo = FALSE;
411 priv->can_redo = FALSE;
412 priv->clipboard_change_handler_id = 0;
413 priv->default_clipboard_change_handler_id = 0;
414 priv->account_removed_handler_id = 0;
415 priv->clipboard_owner_idle = 0;
416 priv->clipboard_text = NULL;
419 priv->scroll_drag_timeout_id = 0;
420 priv->last_upper = 0.0;
422 priv->font_dialog = NULL;
424 if (!is_wp_text_buffer_started) {
425 is_wp_text_buffer_started = TRUE;
426 wp_text_buffer_library_init ();
431 hildon_program_add_window (hildon_program_get_instance(),
437 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
439 static ModestPairList*
440 get_transports (void)
442 GSList *transports = NULL;
444 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
445 GSList *accounts = modest_account_mgr_account_names (account_mgr,
446 TRUE /* only enabled accounts. */);
448 GSList *cursor = accounts;
450 gchar *account_name = cursor->data;
451 gchar *from_string = NULL;
453 from_string = modest_account_mgr_get_from_string (account_mgr,
457 if (from_string && account_name) {
458 gchar *name = account_name;
459 ModestPair *pair = modest_pair_new ((gpointer) name,
460 (gpointer) from_string , TRUE);
461 transports = g_slist_prepend (transports, pair);
464 cursor = cursor->next;
466 g_slist_free (accounts); /* only free the accounts, not the elements,
467 * because they are used in the pairlist */
471 static void window_focus (GtkWindow *window,
475 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
479 scroll_drag_timeout (gpointer userdata)
481 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
482 ModestMsgEditWindowPrivate *priv;
484 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
486 correct_scroll_without_drag_check (win, TRUE);
488 priv->scroll_drag_timeout_id = 0;
494 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
496 ModestMsgEditWindowPrivate *priv;
499 GdkRectangle rectangle;
505 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
507 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
510 insert = gtk_text_buffer_get_insert (priv->text_buffer);
511 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
513 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
514 vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll));
515 offset = priv->msg_body->allocation.y;
517 new_value = vadj->value;
519 if ((offset + rectangle.y + rectangle.height) >
520 ((gint) (vadj->value +vadj->page_size))) {
521 new_value = (offset + rectangle.y) - vadj->page_size * 0.25;
522 if (new_value > vadj->upper - vadj->page_size)
523 new_value = vadj->upper - vadj->page_size;
524 } else if ((offset + rectangle.y) < ((gint) vadj->value)) {
525 new_value = (offset + rectangle.y - vadj->page_size * 0.75);
526 if (((gint) (new_value + vadj->page_size)) < (offset + rectangle.y + rectangle.height))
527 new_value = offset + rectangle.y + rectangle.height - (gint) vadj->page_size;
530 if (new_value > vadj->value)
531 new_value = vadj->value;
534 if (vadj->value != new_value) {
535 g_signal_emit_by_name (GTK_TEXT_VIEW(priv->msg_body)->layout,
537 vadj->value = new_value;
538 gtk_adjustment_value_changed (vadj);
539 /* invalidate body */
540 window = gtk_widget_get_parent_window (priv->msg_body);
542 gdk_window_invalidate_rect (window, NULL, TRUE);
548 correct_scroll (ModestMsgEditWindow *w)
550 ModestMsgEditWindowPrivate *priv;
552 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
553 if (gtk_grab_get_current () == priv->msg_body) {
554 if (priv->scroll_drag_timeout_id == 0) {
555 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
561 correct_scroll_without_drag_check (w, TRUE);
565 text_buffer_end_user_action (GtkTextBuffer *buffer,
566 ModestMsgEditWindow *userdata)
569 correct_scroll (userdata);
573 text_buffer_mark_set (GtkTextBuffer *buffer,
576 ModestMsgEditWindow *userdata)
578 gtk_text_buffer_begin_user_action (buffer);
579 gtk_text_buffer_end_user_action (buffer);
583 cut_clipboard_check (GtkTextView *text_view,
586 GtkTextBuffer *buffer;
588 buffer = gtk_text_view_get_buffer (text_view);
589 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
590 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
595 copy_clipboard_check (GtkTextView *text_view,
598 GtkTextBuffer *buffer;
600 buffer = gtk_text_view_get_buffer (text_view);
601 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
602 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
607 vadj_changed (GtkAdjustment *adj,
608 ModestMsgEditWindow *window)
610 ModestMsgEditWindowPrivate *priv;
612 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
614 if (priv->last_upper != adj->upper) {
615 priv->last_upper = adj->upper;
616 correct_scroll (window);
621 attachment_deleted (ModestAttachmentsView *attachments_view,
624 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
629 connect_signals (ModestMsgEditWindow *obj)
631 ModestMsgEditWindowPrivate *priv;
633 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
635 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
636 G_CALLBACK (text_buffer_refresh_attributes), obj);
637 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
638 G_CALLBACK (text_buffer_can_undo), obj);
639 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
640 G_CALLBACK (text_buffer_can_redo), obj);
641 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
642 G_CALLBACK (body_changed), obj);
643 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
644 G_CALLBACK (body_changed), obj);
645 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
646 G_CALLBACK (text_buffer_end_user_action), obj);
647 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
648 G_CALLBACK (text_buffer_mark_set), obj);
649 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
650 G_CALLBACK (text_buffer_apply_tag), obj);
651 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
652 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
653 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
654 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
655 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
656 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
658 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
659 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
661 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
662 G_CALLBACK (msg_body_focus), obj);
663 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
664 G_CALLBACK (msg_body_focus), obj);
665 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
666 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
667 "changed", G_CALLBACK (recpt_field_changed), obj);
668 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
669 "changed", G_CALLBACK (recpt_field_changed), obj);
670 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
671 "changed", G_CALLBACK (recpt_field_changed), obj);
672 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
673 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
674 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
676 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
677 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
679 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
681 G_CALLBACK (vadj_changed),
684 priv->clipboard_change_handler_id =
685 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
686 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
687 priv->default_clipboard_change_handler_id =
688 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
689 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
691 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
692 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
693 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
697 init_window (ModestMsgEditWindow *obj)
699 GtkWidget *to_caption, *subject_caption;
700 GtkWidget *main_vbox;
701 ModestMsgEditWindowPrivate *priv;
702 GtkActionGroup *action_group;
703 ModestWindowPrivate *parent_priv;
704 GdkPixbuf *window_icon = NULL;
705 GError *error = NULL;
707 GtkSizeGroup *title_size_group;
708 GtkSizeGroup *value_size_group;
709 GtkWidget *subject_box;
710 GtkWidget *attachment_icon;
711 GtkWidget *window_box;
712 #if (GTK_MINOR_VERSION >= 10)
713 GdkAtom deserialize_type;
716 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
717 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
719 parent_priv->ui_manager = gtk_ui_manager_new();
720 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
721 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
723 /* Add common actions */
724 gtk_action_group_add_actions (action_group,
725 modest_msg_edit_action_entries,
726 G_N_ELEMENTS (modest_msg_edit_action_entries),
728 gtk_action_group_add_toggle_actions (action_group,
729 modest_msg_edit_toggle_action_entries,
730 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
732 gtk_action_group_add_radio_actions (action_group,
733 modest_msg_edit_alignment_radio_action_entries,
734 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
736 G_CALLBACK (modest_ui_actions_on_change_justify),
738 gtk_action_group_add_radio_actions (action_group,
739 modest_msg_edit_priority_action_entries,
740 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
742 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
744 gtk_action_group_add_radio_actions (action_group,
745 modest_msg_edit_file_format_action_entries,
746 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
747 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
748 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
750 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
751 g_object_unref (action_group);
753 /* Load the UI definition */
754 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
757 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
758 g_clear_error (&error);
761 /* Add accelerators */
762 gtk_window_add_accel_group (GTK_WINDOW (obj),
763 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
765 parent_priv->menubar = NULL;
767 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
768 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
770 /* Note: This ModestPairList* must exist for as long as the picker
771 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
772 * so it can't know how to manage its memory. */
773 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
774 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
776 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
777 _("mail_va_from"), priv->from_field);
779 priv->to_field = modest_recpt_editor_new ();
780 priv->cc_field = modest_recpt_editor_new ();
781 priv->bcc_field = modest_recpt_editor_new ();
782 subject_box = gtk_hbox_new (FALSE, 0);
783 priv->priority_icon = gtk_image_new ();
784 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
785 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
786 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
787 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
788 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
789 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
790 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
791 priv->add_attachment_button = gtk_button_new ();
792 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
793 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
794 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
795 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 0.5);
796 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
797 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
798 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
799 priv->attachments_view = modest_attachments_view_new (NULL);
801 priv->header_box = gtk_vbox_new (FALSE, 0);
803 to_caption = modest_maemo_utils_create_captioned_with_size_type
804 (title_size_group, value_size_group,
805 _("mail_va_to"), priv->to_field,
806 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
807 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
808 (title_size_group, value_size_group,
809 _("mail_va_cc"), priv->cc_field,
810 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
811 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
812 (title_size_group, value_size_group,
813 _("mail_va_hotfix1"), priv->bcc_field,
814 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
815 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
816 _("mail_va_subject"), subject_box);
817 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
818 _("mail_va_attachment"),
819 priv->attachments_view,
820 HILDON_SIZE_AUTO_WIDTH |
821 HILDON_SIZE_AUTO_HEIGHT);
822 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
823 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
824 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
825 g_object_unref (title_size_group);
826 g_object_unref (value_size_group);
828 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
829 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
830 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
831 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
832 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
833 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
834 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
837 priv->msg_body = wp_text_view_new ();
838 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
839 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
840 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
841 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
842 #if (GTK_MINOR_VERSION >= 10)
843 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
844 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
846 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
847 deserialize_type, TRUE);
849 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
851 priv->find_toolbar = hildon_find_toolbar_new (NULL);
852 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
854 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
856 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
857 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
858 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
859 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
861 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
863 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
864 priv->frame = gtk_frame_new (NULL);
865 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
867 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
868 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
869 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
871 window_box = gtk_vbox_new (FALSE, 0);
872 gtk_container_add (GTK_CONTAINER(obj), window_box);
874 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
876 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
878 /* Set window icon */
879 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
881 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
882 g_object_unref (window_icon);
887 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
889 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
891 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
892 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
893 priv->clipboard_change_handler_id))
894 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
895 priv->clipboard_change_handler_id);
896 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
897 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
898 priv->default_clipboard_change_handler_id))
899 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
900 priv->default_clipboard_change_handler_id);
902 if (priv->account_removed_handler_id &&
903 g_signal_handler_is_connected (modest_runtime_get_account_store (),
904 priv->account_removed_handler_id))
905 g_signal_handler_disconnect(modest_runtime_get_account_store (),
906 priv->account_removed_handler_id);
910 modest_msg_edit_window_finalize (GObject *obj)
912 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
914 /* Sanity check: shouldn't be needed, the window mgr should
915 call this function before */
916 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
918 if (priv->font_dialog != NULL) {
919 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
922 if (priv->clipboard_text != NULL) {
923 g_free (priv->clipboard_text);
924 priv->clipboard_text = NULL;
927 if (priv->draft_msg != NULL) {
928 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
929 if (TNY_IS_HEADER (header)) {
930 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
931 modest_window_mgr_unregister_header (mgr, header);
933 g_object_unref (priv->draft_msg);
934 priv->draft_msg = NULL;
936 if (priv->outbox_msg != NULL) {
937 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
938 if (TNY_IS_HEADER (header)) {
939 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
940 modest_window_mgr_unregister_header (mgr, header);
942 g_object_unref (priv->outbox_msg);
943 priv->outbox_msg = NULL;
945 if (priv->scroll_drag_timeout_id > 0) {
946 g_source_remove (priv->scroll_drag_timeout_id);
947 priv->scroll_drag_timeout_id = 0;
949 if (priv->clipboard_owner_idle > 0) {
950 g_source_remove (priv->clipboard_owner_idle);
951 priv->clipboard_owner_idle = 0;
953 if (priv->original_account_name)
954 g_free (priv->original_account_name);
955 g_free (priv->msg_uid);
956 g_free (priv->last_search);
957 g_slist_free (priv->font_items_group);
958 g_slist_free (priv->size_items_group);
959 g_object_unref (priv->attachments);
960 g_object_unref (priv->images);
962 /* This had to stay alive for as long as the picker that used it: */
963 modest_pair_list_free (priv->from_field_protos);
965 G_OBJECT_CLASS(parent_class)->finalize (obj);
969 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
971 GdkPixbufLoader *loader;
977 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
979 if (loader == NULL) {
985 tny_stream_reset (TNY_STREAM (stream));
986 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
987 GError *error = NULL;
988 unsigned char read_buffer[128];
990 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
992 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
994 g_error_free (error);
999 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1001 g_object_ref (pixbuf);
1002 gdk_pixbuf_loader_close (loader, NULL);
1003 g_object_unref (loader);
1008 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1009 GdkPixbuf *new_pixbuf;
1011 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1012 gdk_pixbuf_get_width (pixbuf);
1013 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1014 g_object_unref (pixbuf);
1015 pixbuf = new_pixbuf;
1019 *stream_size = size;
1025 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1027 ModestMsgEditWindowPrivate *priv;
1030 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1032 for (iter = tny_list_create_iterator (attachments);
1033 !tny_iterator_is_done (iter);
1034 tny_iterator_next (iter)) {
1035 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1036 const gchar *cid = tny_mime_part_get_content_id (part);
1037 const gchar *mime_type = tny_mime_part_get_content_type (part);
1038 if ((cid != NULL)&&(mime_type != NULL)) {
1039 guint64 stream_size;
1040 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1041 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1044 g_object_unref (stream);
1046 if (pixbuf != NULL) {
1047 priv->images_count ++;
1048 priv->images_size += stream_size;
1049 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1050 g_object_unref (pixbuf);
1053 g_object_unref (part);
1055 g_object_unref (iter);
1059 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1061 TnyMimePart *parent = NULL;
1062 const gchar *content_type = NULL;
1063 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1065 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1067 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1068 parent = g_object_ref (msg);
1069 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1070 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1073 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1074 iter = tny_list_create_iterator (parts);
1075 while (!tny_iterator_is_done (iter)) {
1077 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1078 content_type = tny_mime_part_get_content_type (part);
1079 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1083 g_object_unref (part);
1085 tny_iterator_next (iter);
1087 g_object_unref (iter);
1088 g_object_unref (parts);
1091 if (parent != NULL) {
1092 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1095 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1096 iter = tny_list_create_iterator (parts);
1097 while (!tny_iterator_is_done (iter)) {
1099 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1100 content_type = tny_mime_part_get_content_type (part);
1101 if (content_type && g_str_has_prefix (content_type, "image/")) {
1102 tny_list_prepend (priv->images, (GObject *) part);
1104 g_object_unref (part);
1105 tny_iterator_next (iter);
1107 g_object_unref (iter);
1108 g_object_unref (parts);
1109 g_object_unref (parent);
1114 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1117 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1119 for (iter = tny_list_create_iterator (attachments) ;
1120 !tny_iterator_is_done (iter);
1121 tny_iterator_next (iter)) {
1122 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1123 const gchar *cid = tny_mime_part_get_content_id (part);
1125 char *invalid = NULL;
1126 gint int_cid = strtol (cid, &invalid, 10);
1127 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1128 priv->next_cid = int_cid + 1;
1131 g_object_unref (part);
1133 g_object_unref (iter);
1137 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1140 gchar *to, *cc, *bcc, *subject;
1142 ModestMsgEditWindowPrivate *priv;
1144 TnyHeaderFlags priority_flags;
1145 TnyFolder *msg_folder;
1146 gboolean is_html = FALSE;
1148 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1149 g_return_if_fail (TNY_IS_MSG (msg));
1151 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1153 header = tny_msg_get_header (msg);
1154 to = tny_header_dup_to (header);
1155 cc = tny_header_dup_cc (header);
1156 bcc = tny_header_dup_bcc (header);
1157 subject = tny_header_dup_subject (header);
1158 priority_flags = tny_header_get_priority (header);
1161 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1163 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1164 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1165 gtk_widget_show (priv->cc_caption);
1166 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1167 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1168 gtk_widget_hide (priv->cc_caption);
1171 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1172 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1173 gtk_widget_show (priv->bcc_caption);
1174 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1175 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1176 gtk_widget_hide (priv->bcc_caption);
1179 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1180 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1183 update_window_title (self);
1185 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1186 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1188 if ((body == NULL)||(body[0] == '\0')) {
1190 body = modest_text_utils_convert_to_html ("");
1193 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1194 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1197 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1200 /* Add attachments to the view */
1201 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1202 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1203 if (tny_list_get_length (priv->attachments) == 0) {
1204 gtk_widget_hide (priv->attachments_caption);
1206 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1207 gtk_widget_show_all (priv->attachments_caption);
1209 get_related_images (self, msg);
1210 update_next_cid (self, priv->attachments);
1211 update_next_cid (self, priv->images);
1212 replace_with_images (self, priv->images);
1214 if (preserve_is_rich && !is_html) {
1215 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1216 /* Get the default format required from configuration */
1217 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1218 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1221 /* Set the default focus depending on having already a To: field or not */
1222 if ((!to)||(*to == '\0')) {
1223 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1225 gtk_widget_grab_focus (priv->msg_body);
1228 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1230 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1231 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1233 modest_msg_edit_window_set_modified (self, FALSE);
1235 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1236 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1237 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1238 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1240 if (priv->msg_uid) {
1241 g_free (priv->msg_uid);
1242 priv->msg_uid = NULL;
1245 /* we should set a reference to the incoming message if it is a draft */
1246 msg_folder = tny_msg_get_folder (msg);
1248 if (modest_tny_folder_is_local_folder (msg_folder)) {
1249 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1250 if (type == TNY_FOLDER_TYPE_INVALID)
1251 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1253 if (type == TNY_FOLDER_TYPE_DRAFTS)
1254 priv->draft_msg = g_object_ref(msg);
1255 if (type == TNY_FOLDER_TYPE_OUTBOX)
1256 priv->outbox_msg = g_object_ref(msg);
1257 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1259 g_object_unref (msg_folder);
1269 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1272 GList *item_children, *node;
1273 GtkWidget *bin_child;
1275 bin_child = gtk_bin_get_child (GTK_BIN(item));
1277 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1279 for (node = item_children; node != NULL; node = g_list_next (node)) {
1280 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1281 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1284 g_list_free (item_children);
1288 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1291 GList *item_children, *node;
1293 box = gtk_bin_get_child (GTK_BIN (item));
1294 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1295 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1297 for (node = item_children; node != NULL; node = g_list_next (node)) {
1298 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1299 if (GTK_IS_TOGGLE_BUTTON (node->data))
1300 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1301 else if (GTK_IS_BUTTON (node->data))
1302 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1304 g_list_free (item_children);
1309 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1311 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1312 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1313 GtkWidget *placeholder;
1314 GtkWidget *tool_item;
1319 GtkWidget *sizes_menu;
1320 GtkWidget *fonts_menu;
1321 GSList *radio_group = NULL;
1322 GSList *node = NULL;
1326 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1327 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1329 /* Font color placeholder */
1330 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1331 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1334 tool_item = GTK_WIDGET (gtk_tool_item_new ());
1335 priv->font_color_button = hildon_color_button_new ();
1336 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1337 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1338 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
1339 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1340 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1341 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1342 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1344 G_CALLBACK (modest_msg_edit_window_color_button_change),
1347 /* Font size and face placeholder */
1348 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1349 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1351 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1352 priv->size_tool_button_label = gtk_label_new (NULL);
1353 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1354 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1355 size_text,"</span>", NULL);
1356 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1358 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1359 sizes_menu = gtk_menu_new ();
1360 priv->size_items_group = NULL;
1362 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1363 GtkWidget *size_menu_item;
1365 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1366 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1367 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1368 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1369 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1370 gtk_widget_show (size_menu_item);
1372 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1376 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1377 GtkWidget *item = (GtkWidget *) node->data;
1378 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1382 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1383 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1384 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1385 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1386 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1387 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1388 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1389 priv->font_size_toolitem = tool_item;
1392 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1393 priv->font_tool_button_label = gtk_label_new (NULL);
1394 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1395 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1397 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1398 fonts_menu = gtk_menu_new ();
1399 priv->font_items_group = NULL;
1401 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1402 GtkWidget *font_menu_item;
1403 GtkWidget *child_label;
1405 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1406 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1407 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1408 wp_get_font_name (font_index), "</span>", NULL);
1409 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1412 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1413 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1414 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1415 gtk_widget_show (font_menu_item);
1417 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1420 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1421 GtkWidget *item = (GtkWidget *) node->data;
1422 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1425 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1426 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1427 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1428 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1429 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1430 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1431 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1432 priv->font_face_toolitem = tool_item;
1434 /* Set expand and homogeneous for remaining items */
1435 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1436 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1437 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1438 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1439 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1440 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1441 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1442 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1443 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1445 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1446 will not show the tool items added to the placeholders) */
1447 gtk_widget_show_all (parent_priv->toolbar);
1449 /* Set the no show all *after* showing all items. We do not
1450 want the toolbar to be shown with a show all because it
1451 could go agains the gconf setting regarding showing or not
1452 the toolbar of the editor window */
1453 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1459 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1462 ModestWindowPrivate *parent_priv;
1463 ModestMsgEditWindowPrivate *priv;
1464 ModestDimmingRulesGroup *menu_rules_group = NULL;
1465 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1466 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1467 ModestWindowMgr *mgr = NULL;
1469 g_return_val_if_fail (msg, NULL);
1470 g_return_val_if_fail (account_name, NULL);
1472 mgr = modest_runtime_get_window_mgr ();
1474 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1476 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1477 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1479 /* Menubar. Update the state of some toggles */
1480 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1481 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1482 priv->from_field_protos = get_transports ();
1483 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1484 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1485 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1487 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1488 hildon_touch_selector_get_current_text
1489 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1490 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1491 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1494 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1496 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1498 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1500 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1502 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1503 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1504 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1505 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1506 /* Add common dimming rules */
1507 modest_dimming_rules_group_add_rules (menu_rules_group,
1508 modest_msg_edit_window_menu_dimming_entries,
1509 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1510 MODEST_WINDOW (obj));
1511 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1512 modest_msg_edit_window_toolbar_dimming_entries,
1513 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1514 MODEST_WINDOW (obj));
1515 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1516 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1517 MODEST_WINDOW (obj));
1518 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1519 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1520 MODEST_WINDOW (obj));
1521 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1522 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1523 MODEST_WINDOW (obj));
1524 /* Insert dimming rules group for this window */
1525 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1526 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1527 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1528 /* Checks the dimming rules */
1529 g_object_unref (menu_rules_group);
1530 g_object_unref (toolbar_rules_group);
1531 g_object_unref (clipboard_rules_group);
1532 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1534 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1536 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1537 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1538 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1539 priv->update_caption_visibility = TRUE;
1541 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1543 /* Track account-removed signal, this window should be closed
1544 in the case we're creating a mail associated to the account
1546 priv->account_removed_handler_id =
1547 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1549 G_CALLBACK(on_account_removed),
1552 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1554 return (ModestWindow*) obj;
1558 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1560 GString **string_buffer = (GString **) user_data;
1562 *string_buffer = g_string_append (*string_buffer, buffer);
1568 * @result: A new string which should be freed with g_free().
1571 get_formatted_data (ModestMsgEditWindow *edit_window)
1573 ModestMsgEditWindowPrivate *priv;
1574 GString *string_buffer = g_string_new ("");
1576 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1578 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1580 modest_text_utils_hyperlinkify (string_buffer);
1582 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1584 return g_string_free (string_buffer, FALSE);
1589 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1592 const gchar *account_name;
1593 ModestMsgEditWindowPrivate *priv;
1594 TnyIterator *att_iter;
1596 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1598 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1600 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1601 g_return_val_if_fail (account_name, NULL);
1604 /* don't free these (except from) */
1605 data = g_slice_new0 (MsgData);
1606 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1608 data->account_name = g_strdup (account_name);
1609 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1610 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1611 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1612 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1613 if (priv->draft_msg) {
1614 data->draft_msg = g_object_ref (priv->draft_msg);
1615 } else if (priv->outbox_msg) {
1616 data->draft_msg = g_object_ref (priv->outbox_msg);
1618 data->draft_msg = NULL;
1621 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1623 gtk_text_buffer_get_bounds (buf, &b, &e);
1624 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1626 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1627 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1629 data->html_body = NULL;
1631 /* deep-copy the data */
1632 att_iter = tny_list_create_iterator (priv->attachments);
1633 data->attachments = NULL;
1634 while (!tny_iterator_is_done (att_iter)) {
1635 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1636 if (!(TNY_IS_MIME_PART(part))) {
1637 g_warning ("strange data in attachment list");
1638 g_object_unref (part);
1639 tny_iterator_next (att_iter);
1642 data->attachments = g_list_append (data->attachments,
1644 tny_iterator_next (att_iter);
1646 g_object_unref (att_iter);
1648 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1649 att_iter = tny_list_create_iterator (priv->images);
1650 data->images = NULL;
1651 while (!tny_iterator_is_done (att_iter)) {
1652 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1654 if (!(TNY_IS_MIME_PART(part))) {
1655 g_warning ("strange data in attachment list");
1656 g_object_unref (part);
1657 tny_iterator_next (att_iter);
1660 cid = tny_mime_part_get_content_id (part);
1662 gchar *image_tag_id;
1663 GtkTextTag *image_tag;
1665 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1666 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1667 g_free (image_tag_id);
1669 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1671 ((gtk_text_iter_has_tag (&iter, image_tag))||
1672 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1673 data->images = g_list_append (data->images,
1674 g_object_ref (part));
1676 g_object_unref (part);
1677 tny_iterator_next (att_iter);
1679 g_object_unref (att_iter);
1681 data->priority_flags = priv->priority_flags;
1688 unref_gobject (GObject *obj, gpointer data)
1690 if (!G_IS_OBJECT(obj))
1692 g_object_unref (obj);
1696 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1699 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1707 g_free (data->from);
1708 g_free (data->subject);
1709 g_free (data->plain_body);
1710 g_free (data->html_body);
1711 g_free (data->account_name);
1713 if (data->draft_msg != NULL) {
1714 g_object_unref (data->draft_msg);
1715 data->draft_msg = NULL;
1718 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1719 g_list_free (data->attachments);
1720 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1721 g_list_free (data->images);
1723 g_slice_free (MsgData, data);
1727 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1729 guint64 *parts_size)
1731 ModestMsgEditWindowPrivate *priv;
1733 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1735 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1737 /* TODO: add images */
1738 *parts_size += priv->images_size;
1739 *parts_count += priv->images_count;
1744 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1747 ModestMsgEditWindowPrivate *priv = NULL;
1748 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1750 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1752 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1754 return MODEST_MSG_EDIT_FORMAT_HTML;
1756 return MODEST_MSG_EDIT_FORMAT_TEXT;
1760 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1761 ModestMsgEditFormat format)
1763 ModestMsgEditWindowPrivate *priv;
1765 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1766 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1769 case MODEST_MSG_EDIT_FORMAT_HTML:
1770 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1772 case MODEST_MSG_EDIT_FORMAT_TEXT:
1773 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1776 g_return_if_reached ();
1780 ModestMsgEditFormatState *
1781 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1783 ModestMsgEditFormatState *format_state = NULL;
1784 ModestMsgEditWindowPrivate *priv;
1785 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1787 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1788 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1790 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1792 format_state = g_new0 (ModestMsgEditFormatState, 1);
1793 format_state->bold = buffer_format->bold&0x1;
1794 format_state->italics = buffer_format->italic&0x1;
1795 format_state->bullet = buffer_format->bullet&0x1;
1796 format_state->color = buffer_format->color;
1797 format_state->font_size = buffer_format->font_size;
1798 format_state->font_family = wp_get_font_name (buffer_format->font);
1799 format_state->justification = buffer_format->justification;
1800 g_free (buffer_format);
1802 return format_state;
1807 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1808 const ModestMsgEditFormatState *format_state)
1810 ModestMsgEditWindowPrivate *priv;
1811 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1812 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1813 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1814 g_return_if_fail (format_state != NULL);
1816 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1817 gtk_widget_grab_focus (priv->msg_body);
1818 buffer_format->bold = (format_state->bold != FALSE);
1819 buffer_format->italic = (format_state->italics != FALSE);
1820 buffer_format->color = format_state->color;
1821 buffer_format->font_size = format_state->font_size;
1822 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1823 buffer_format->justification = format_state->justification;
1824 buffer_format->bullet = format_state->bullet;
1826 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1828 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1829 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1830 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1831 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1832 buffer_format->cs.font = (buffer_format->font != current_format->font);
1833 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1834 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1836 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1837 if (buffer_format->cs.bold) {
1838 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1839 GINT_TO_POINTER (buffer_format->bold&0x1));
1841 if (buffer_format->cs.italic) {
1842 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1843 GINT_TO_POINTER (buffer_format->italic&0x1));
1845 if (buffer_format->cs.color) {
1846 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1847 GINT_TO_POINTER (&(buffer_format->color)));
1849 if (buffer_format->cs.font_size) {
1850 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1851 GINT_TO_POINTER (buffer_format->font_size));
1853 if (buffer_format->cs.justification) {
1854 switch (buffer_format->justification) {
1855 case GTK_JUSTIFY_LEFT:
1856 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1857 GINT_TO_POINTER(TRUE));
1859 case GTK_JUSTIFY_CENTER:
1860 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1861 GINT_TO_POINTER(TRUE));
1863 case GTK_JUSTIFY_RIGHT:
1864 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1865 GINT_TO_POINTER(TRUE));
1872 if (buffer_format->cs.font) {
1873 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1874 GINT_TO_POINTER (buffer_format->font));
1876 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1877 if (buffer_format->cs.bullet) {
1878 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1879 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1881 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1883 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1885 g_free (buffer_format);
1886 g_free (current_format);
1888 /* Check dimming rules */
1889 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1890 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1894 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1896 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1898 ModestWindowPrivate *parent_priv;
1899 ModestMsgEditWindowPrivate *priv;
1900 GtkWidget *new_size_menuitem;
1901 GtkWidget *new_font_menuitem;
1903 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1904 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1906 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1907 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1908 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1909 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1911 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1912 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1913 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1916 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1918 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1919 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1921 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1922 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1924 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1925 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1928 switch (buffer_format->justification)
1930 case GTK_JUSTIFY_LEFT:
1931 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1933 case GTK_JUSTIFY_CENTER:
1934 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1936 case GTK_JUSTIFY_RIGHT:
1937 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1944 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1946 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1947 G_CALLBACK (modest_msg_edit_window_color_button_change),
1949 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1950 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1951 G_CALLBACK (modest_msg_edit_window_color_button_change),
1954 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1955 buffer_format->font_size))->data);
1956 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1960 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1961 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1962 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1964 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1965 G_CALLBACK (modest_msg_edit_window_size_change),
1967 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1968 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1969 G_CALLBACK (modest_msg_edit_window_size_change),
1973 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1974 buffer_format->font))->data);
1975 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1979 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1980 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1981 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1983 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1984 G_CALLBACK (modest_msg_edit_window_font_change),
1986 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1987 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1988 G_CALLBACK (modest_msg_edit_window_font_change),
1992 g_free (buffer_format);
1996 #ifdef MODEST_HILDON_VERSION_0
1998 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2001 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2002 ModestMsgEditWindowPrivate *priv;
2003 GtkWidget *dialog = NULL;
2005 GdkColor *new_color = NULL;
2007 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2008 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2010 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2011 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2012 g_free (buffer_format);
2014 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2015 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2016 if (new_color != NULL) {
2017 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2018 (gpointer) new_color);
2021 gtk_widget_destroy (dialog);
2026 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2029 ModestMsgEditWindowPrivate *priv;
2030 GtkWidget *dialog = NULL;
2032 GdkColor *old_color = NULL;
2033 const GdkColor *new_color = NULL;
2035 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2036 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2038 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2039 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2041 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2042 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2043 if (new_color != NULL)
2044 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2046 gtk_widget_destroy (dialog);
2052 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2055 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2056 ModestMsgEditWindowPrivate *priv;
2057 GtkWidget *dialog = NULL;
2059 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2060 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2062 dialog = hildon_color_chooser_new ();
2063 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2064 g_free (buffer_format);
2066 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2068 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2069 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2072 gtk_widget_destroy (dialog);
2077 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2080 ModestMsgEditWindowPrivate *priv;
2081 GtkWidget *dialog = NULL;
2082 GdkColor *old_color = NULL;
2084 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2085 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2087 dialog = hildon_color_chooser_new ();
2088 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2090 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2092 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2093 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2095 gtk_widget_destroy (dialog);
2098 #endif /*!MODEST_HILDON_VERSION_0*/
2103 create_stream_for_uri (const gchar* uri)
2108 TnyStream *result = NULL;
2110 GnomeVFSHandle *handle = NULL;
2111 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2112 if (test == GNOME_VFS_OK) {
2113 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2114 /* Streams over OBEX (Bluetooth) are not seekable but
2115 * we expect them to be (we might need to read them
2116 * several times). So if this is a Bluetooth URI just
2117 * read the whole file into memory (this is not a fast
2118 * protocol so we can assume that these files are not
2119 * going to be very big) */
2120 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2121 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2122 TnyStream *memstream = tny_camel_mem_stream_new ();
2123 tny_stream_write_to_stream (vfssstream, memstream);
2124 g_object_unref (vfssstream);
2127 result = vfssstream;
2135 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2138 ModestMsgEditWindowPrivate *priv;
2139 GtkWidget *dialog = NULL;
2141 GSList *uris = NULL;
2142 GSList *uri_node = NULL;
2144 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2146 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2147 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2148 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2150 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2152 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2153 GTK_WINDOW (dialog), GTK_WINDOW (window));
2155 response = gtk_dialog_run (GTK_DIALOG (dialog));
2157 case GTK_RESPONSE_OK:
2158 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2163 gtk_widget_destroy (dialog);
2165 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2167 GnomeVFSHandle *handle = NULL;
2168 GnomeVFSResult result;
2169 GtkTextIter position;
2170 GtkTextMark *insert_mark;
2172 uri = (const gchar *) uri_node->data;
2173 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2174 if (result == GNOME_VFS_OK) {
2176 GnomeVFSFileInfo *info;
2177 gchar *filename, *basename, *escaped_filename;
2178 TnyMimePart *mime_part;
2180 const gchar *mime_type = NULL;
2181 GnomeVFSURI *vfs_uri;
2182 guint64 stream_size;
2184 gnome_vfs_close (handle);
2185 vfs_uri = gnome_vfs_uri_new (uri);
2187 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2188 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2189 g_free (escaped_filename);
2190 gnome_vfs_uri_unref (vfs_uri);
2191 info = gnome_vfs_file_info_new ();
2193 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2194 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2196 mime_type = gnome_vfs_file_info_get_mime_type (info);
2198 mime_part = tny_platform_factory_new_mime_part
2199 (modest_runtime_get_platform_factory ());
2201 TnyStream *stream = create_stream_for_uri (uri);
2203 if (stream == NULL) {
2205 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2207 g_object_unref (mime_part);
2208 gnome_vfs_file_info_unref (info);
2212 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2214 content_id = g_strdup_printf ("%d", priv->next_cid);
2215 tny_mime_part_set_content_id (mime_part, content_id);
2216 g_free (content_id);
2219 basename = g_path_get_basename (filename);
2220 tny_mime_part_set_filename (mime_part, basename);
2223 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2225 if (pixbuf != NULL) {
2226 priv->images_size += stream_size;
2227 priv->images_count ++;
2228 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2229 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2230 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2231 g_object_unref (pixbuf);
2234 tny_list_prepend (priv->images, (GObject *) mime_part);
2235 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2237 g_object_unref (mime_part);
2238 gnome_vfs_file_info_unref (info);
2247 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2249 GtkWidget *dialog = NULL;
2251 GSList *uris = NULL;
2253 GnomeVFSFileSize total_size, allowed_size;
2254 ModestMsgEditWindowPrivate *priv;
2258 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2260 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2262 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2265 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2266 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2267 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2268 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), GTK_WINDOW (window));
2270 response = gtk_dialog_run (GTK_DIALOG (dialog));
2272 case GTK_RESPONSE_OK:
2273 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2278 gtk_widget_destroy (dialog);
2280 /* allowed size is the maximum size - what's already there */
2281 modest_attachments_view_get_sizes (
2282 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2283 &att_num, &att_size);
2284 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2287 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2289 const gchar *uri = (const gchar *) uri_node->data;
2291 total_size += modest_msg_edit_window_attach_file_one
2292 (window, uri, allowed_size);
2294 if (total_size > allowed_size) {
2295 g_warning ("%s: total size: %u",
2296 __FUNCTION__, (unsigned int)total_size);
2300 allowed_size -= total_size;
2304 g_slist_foreach (uris, (GFunc) g_free, NULL);
2305 g_slist_free (uris);
2310 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2312 GnomeVFSFileSize allowed_size)
2315 GnomeVFSHandle *handle = NULL;
2316 ModestMsgEditWindowPrivate *priv;
2317 GnomeVFSResult result;
2318 GnomeVFSFileSize size = 0;
2319 g_return_val_if_fail (window, 0);
2320 g_return_val_if_fail (uri, 0);
2322 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2324 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2325 if (result == GNOME_VFS_OK) {
2326 TnyMimePart *mime_part;
2328 const gchar *mime_type = NULL;
2330 gchar *escaped_filename;
2333 GnomeVFSFileInfo *info;
2334 GnomeVFSURI *vfs_uri;
2336 gnome_vfs_close (handle);
2337 vfs_uri = gnome_vfs_uri_new (uri);
2340 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2341 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2342 g_free (escaped_filename);
2343 gnome_vfs_uri_unref (vfs_uri);
2345 info = gnome_vfs_file_info_new ();
2347 if (gnome_vfs_get_file_info (uri,
2349 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2351 mime_type = gnome_vfs_file_info_get_mime_type (info);
2352 mime_part = tny_platform_factory_new_mime_part
2353 (modest_runtime_get_platform_factory ());
2355 /* try to get the attachment's size; this may fail for weird
2356 * file systems, like obex, upnp... */
2357 if (allowed_size != 0 &&
2358 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2360 if (size > allowed_size) {
2361 modest_platform_information_banner (NULL, NULL,
2362 dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2366 g_warning ("%s: could not get attachment size", __FUNCTION__);
2368 stream = create_stream_for_uri (uri);
2370 if (stream == NULL) {
2372 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2374 g_object_unref (mime_part);
2375 gnome_vfs_file_info_unref (info);
2379 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2380 g_object_unref (stream);
2382 content_id = g_strdup_printf ("%d", priv->next_cid);
2383 tny_mime_part_set_content_id (mime_part, content_id);
2384 g_free (content_id);
2387 basename = g_path_get_basename (filename);
2388 tny_mime_part_set_filename (mime_part, basename);
2391 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2392 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2394 info->size == 0, info->size);
2395 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2396 gtk_widget_show_all (priv->attachments_caption);
2397 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2399 g_object_unref (mime_part);
2400 gnome_vfs_file_info_unref (info);
2407 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2410 ModestMsgEditWindowPrivate *priv;
2413 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2414 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2416 if (att_list == NULL) {
2417 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2419 g_object_ref (att_list);
2422 if (tny_list_get_length (att_list) == 0) {
2423 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2425 gboolean dialog_response;
2426 gchar *message = NULL;
2427 gchar *filename = NULL;
2429 if (tny_list_get_length (att_list) == 1) {
2431 iter = tny_list_create_iterator (att_list);
2432 part = (TnyMimePart *) tny_iterator_get_current (iter);
2433 g_object_unref (iter);
2434 if (TNY_IS_MSG (part)) {
2435 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2437 filename = tny_header_dup_subject (header);
2438 g_object_unref (header);
2440 if (filename == NULL) {
2441 filename = g_strdup (_("mail_va_no_subject"));
2444 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2446 g_object_unref (part);
2448 filename = g_strdup ("");
2450 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2451 tny_list_get_length (att_list)), filename);
2454 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2457 if (dialog_response != GTK_RESPONSE_OK) {
2458 g_object_unref (att_list);
2461 hildon_banner_show_information (NULL, NULL, _("mcen_me_inbox_remove_attachments"));
2463 for (iter = tny_list_create_iterator (att_list);
2464 !tny_iterator_is_done (iter);
2465 tny_iterator_next (iter)) {
2466 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2467 const gchar *att_id;
2468 tny_list_remove (priv->attachments, (GObject *) mime_part);
2470 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2472 if (tny_list_get_length (priv->attachments) == 0)
2473 gtk_widget_hide (priv->attachments_caption);
2474 att_id = tny_mime_part_get_content_id (mime_part);
2476 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2478 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2479 g_object_unref (mime_part);
2481 g_object_unref (iter);
2484 g_object_unref (att_list);
2486 /* if the last attachment has been removed, focus the Subject: field */
2487 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2488 gtk_widget_grab_focus (priv->subject_field);
2492 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2495 ModestMsgEditWindowPrivate *priv;
2496 GdkColor *new_color;
2497 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2499 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2500 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2503 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2505 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2507 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2509 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2514 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2517 ModestMsgEditWindowPrivate *priv;
2518 gint new_size_index;
2519 ModestMsgEditWindow *window;
2522 window = MODEST_MSG_EDIT_WINDOW (userdata);
2523 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2524 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2526 if (gtk_check_menu_item_get_active (menu_item)) {
2528 WPTextBufferFormat format;
2530 memset (&format, 0, sizeof (format));
2531 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2533 label = gtk_bin_get_child (GTK_BIN (menu_item));
2535 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2536 format.cs.font_size = TRUE;
2537 format.cs.text_position = TRUE;
2538 format.cs.font = TRUE;
2539 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2540 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2542 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2543 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2544 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2546 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2547 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2548 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2554 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2557 ModestMsgEditWindowPrivate *priv;
2558 gint new_font_index;
2559 ModestMsgEditWindow *window;
2562 window = MODEST_MSG_EDIT_WINDOW (userdata);
2563 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2564 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2566 if (gtk_check_menu_item_get_active (menu_item)) {
2569 label = gtk_bin_get_child (GTK_BIN (menu_item));
2571 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2573 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2574 GINT_TO_POINTER(new_font_index)))
2575 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2577 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2578 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2579 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2585 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2588 ModestMsgEditWindowPrivate *priv = NULL;
2589 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2591 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2592 if (!priv->update_caption_visibility)
2595 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2597 gtk_widget_show (priv->cc_caption);
2599 gtk_widget_hide (priv->cc_caption);
2601 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2605 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2608 ModestMsgEditWindowPrivate *priv = NULL;
2609 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2611 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2612 if (!priv->update_caption_visibility)
2615 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2617 gtk_widget_show (priv->bcc_caption);
2619 gtk_widget_hide (priv->bcc_caption);
2621 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2625 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2626 ModestRecptEditor *editor)
2628 ModestMsgEditWindowPrivate *priv;
2630 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2631 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2633 /* we check for low-mem; in that case, show a warning, and don't allow
2634 * for the addressbook
2636 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2639 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2641 if (editor == NULL) {
2642 GtkWidget *view_focus;
2643 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2645 /* This code should be kept in sync with ModestRecptEditor. The
2646 textview inside the recpt editor is the one that really gets the
2647 focus. As it's inside a scrolled window, and this one inside the
2648 hbox recpt editor inherits from, we'll need to go up in the
2649 hierarchy to know if the text view is part of the recpt editor
2650 or if it's a different text entry */
2652 if (gtk_widget_get_parent (view_focus)) {
2653 GtkWidget *first_parent;
2655 first_parent = gtk_widget_get_parent (view_focus);
2656 if (gtk_widget_get_parent (first_parent) &&
2657 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2658 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2663 editor = MODEST_RECPT_EDITOR (priv->to_field);
2667 modest_address_book_select_addresses (editor);
2672 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2674 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2676 modest_msg_edit_window_open_addressbook (window, NULL);
2680 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2681 gboolean show_toolbar)
2683 ModestWindowPrivate *parent_priv;
2685 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2686 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2688 /* We can not just use the code of
2689 modest_msg_edit_window_setup_toolbar because it has a
2690 mixture of both initialization and creation code. */
2692 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2694 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2698 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2699 TnyHeaderFlags priority_flags)
2701 ModestMsgEditWindowPrivate *priv;
2702 ModestWindowPrivate *parent_priv;
2704 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2706 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2707 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2709 if (priv->priority_flags != priority_flags) {
2710 GtkAction *priority_action = NULL;
2712 priv->priority_flags = priority_flags;
2714 switch (priority_flags) {
2715 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2716 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2717 MODEST_HEADER_ICON_HIGH,
2718 HILDON_ICON_SIZE_XSMALL);
2719 gtk_widget_show (priv->priority_icon);
2720 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2721 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2723 case TNY_HEADER_FLAG_LOW_PRIORITY:
2724 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2725 MODEST_HEADER_ICON_LOW,
2726 HILDON_ICON_SIZE_XSMALL);
2727 gtk_widget_show (priv->priority_icon);
2728 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2729 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2732 gtk_widget_hide (priv->priority_icon);
2733 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2734 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2737 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2738 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2743 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2746 ModestMsgEditWindowPrivate *priv;
2747 ModestWindowPrivate *parent_priv;
2748 gint current_format;
2750 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2752 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2753 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2755 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2756 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2758 if (current_format != file_format) {
2759 switch (file_format) {
2760 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2761 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2762 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2764 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2768 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2769 response = gtk_dialog_run (GTK_DIALOG (dialog));
2770 gtk_widget_destroy (dialog);
2771 if (response == GTK_RESPONSE_OK) {
2772 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2774 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2775 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2780 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2781 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2782 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2787 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2790 ModestMsgEditWindowPrivate *priv;
2791 WPTextBufferFormat oldfmt, fmt;
2792 gint old_position = 0;
2796 GdkColor *color = NULL;
2797 gboolean bold, bold_set, italic, italic_set;
2798 gboolean underline, underline_set;
2799 gboolean strikethrough, strikethrough_set;
2800 gboolean position_set;
2801 gboolean font_size_set, font_set, color_set;
2804 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2805 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2807 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2808 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2809 GTK_WINDOW(dialog), GTK_WINDOW (window));
2811 /* First we get the currently selected font information */
2812 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2814 switch (oldfmt.text_position) {
2815 case TEXT_POSITION_NORMAL:
2818 case TEXT_POSITION_SUPERSCRIPT:
2826 g_object_set (G_OBJECT (dialog),
2827 "bold", oldfmt.bold != FALSE,
2828 "bold-set", !oldfmt.cs.bold,
2829 "underline", oldfmt.underline != FALSE,
2830 "underline-set", !oldfmt.cs.underline,
2831 "italic", oldfmt.italic != FALSE,
2832 "italic-set", !oldfmt.cs.italic,
2833 "strikethrough", oldfmt.strikethrough != FALSE,
2834 "strikethrough-set", !oldfmt.cs.strikethrough,
2835 "color", &oldfmt.color,
2836 "color-set", !oldfmt.cs.color,
2837 "size", wp_font_size[oldfmt.font_size],
2838 "size-set", !oldfmt.cs.font_size,
2839 "position", old_position,
2840 "position-set", !oldfmt.cs.text_position,
2841 "family", wp_get_font_name (oldfmt.font),
2842 "family-set", !oldfmt.cs.font,
2845 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2846 GTK_WINDOW (dialog), GTK_WINDOW (window));
2847 gtk_widget_show_all (dialog);
2848 priv->font_dialog = dialog;
2849 response = gtk_dialog_run (GTK_DIALOG (dialog));
2850 priv->font_dialog = NULL;
2851 if (response == GTK_RESPONSE_OK) {
2853 g_object_get( dialog,
2855 "bold-set", &bold_set,
2856 "underline", &underline,
2857 "underline-set", &underline_set,
2859 "italic-set", &italic_set,
2860 "strikethrough", &strikethrough,
2861 "strikethrough-set", &strikethrough_set,
2863 "color-set", &color_set,
2865 "size-set", &font_size_set,
2866 "family", &font_name,
2867 "family-set", &font_set,
2868 "position", &position,
2869 "position-set", &position_set,
2874 if (response == GTK_RESPONSE_OK) {
2875 memset(&fmt, 0, sizeof(fmt));
2881 fmt.italic = italic;
2882 fmt.cs.italic = TRUE;
2884 if (underline_set) {
2885 fmt.underline = underline;
2886 fmt.cs.underline = TRUE;
2888 if (strikethrough_set) {
2889 fmt.strikethrough = strikethrough;
2890 fmt.cs.strikethrough = TRUE;
2895 ? TEXT_POSITION_NORMAL
2896 : ( ( position == 1 )
2897 ? TEXT_POSITION_SUPERSCRIPT
2898 : TEXT_POSITION_SUBSCRIPT );
2899 fmt.cs.text_position = TRUE;
2900 fmt.font_size = oldfmt.font_size;
2904 fmt.cs.color = TRUE;
2907 fmt.font = wp_get_font_index(font_name,
2912 if (font_size_set) {
2913 fmt.cs.font_size = TRUE;
2914 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2916 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2917 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2919 gtk_widget_destroy (dialog);
2921 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2925 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2927 ModestMsgEditWindowPrivate *priv;
2929 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2930 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2932 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2934 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2935 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2939 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2941 ModestMsgEditWindowPrivate *priv;
2943 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2944 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2946 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2948 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2949 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2954 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2956 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2958 priv->can_undo = can_undo;
2962 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2964 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2966 priv->can_redo = can_redo;
2970 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2972 ModestMsgEditWindowPrivate *priv;
2973 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2974 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2976 return priv->can_undo;
2980 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2982 ModestMsgEditWindowPrivate *priv;
2983 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2984 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2986 return priv->can_redo;
2991 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2994 GtkTextIter match_start, match_end;
2996 if (image_id == NULL)
2999 gtk_text_buffer_get_start_iter (buffer, &iter);
3001 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3002 GSList *tags = gtk_text_iter_get_tags (&match_start);
3004 for (node = tags; node != NULL; node = g_slist_next (node)) {
3005 GtkTextTag *tag = (GtkTextTag *) node->data;
3006 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3007 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3008 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3010 offset = gtk_text_iter_get_offset (&match_start);
3011 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3012 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3016 gtk_text_iter_forward_char (&iter);
3021 message_is_empty (ModestMsgEditWindow *window)
3023 ModestMsgEditWindowPrivate *priv = NULL;
3025 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3026 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3028 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3029 * so we can ignore markup.
3031 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3034 count = gtk_text_buffer_get_char_count (buf);
3040 msg_body_focus (GtkWidget *focus,
3041 GdkEventFocus *event,
3045 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3046 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3047 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3052 recpt_field_changed (GtkTextBuffer *buffer,
3053 ModestMsgEditWindow *editor)
3055 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3056 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3060 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3062 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3063 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3067 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3070 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3071 GtkTextBuffer *buffer;
3073 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3074 gtk_text_buffer_set_modified (buffer, modified);
3075 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3076 gtk_text_buffer_set_modified (buffer, modified);
3077 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3078 gtk_text_buffer_set_modified (buffer, modified);
3079 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3083 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3085 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3086 const char *account_name;
3087 GtkTextBuffer *buffer;
3089 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3090 if (gtk_text_buffer_get_modified (buffer))
3092 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3093 if (gtk_text_buffer_get_modified (buffer))
3095 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3096 if (gtk_text_buffer_get_modified (buffer))
3098 if (gtk_text_buffer_get_modified (priv->text_buffer))
3100 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3101 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3112 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3114 ModestMsgEditWindowPrivate *priv = NULL;
3116 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3117 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3119 /* check if there's no recipient added */
3120 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3121 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3122 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3123 /* no recipient contents, then select contacts */
3124 modest_msg_edit_window_open_addressbook (window, NULL);
3128 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3129 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3132 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3133 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3136 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3137 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3141 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3142 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3143 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3150 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3151 ModestMsgEditWindow *window)
3153 modest_msg_edit_window_offer_attach_file (window);
3157 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3159 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3161 return priv->clipboard_text;
3165 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3167 ModestMsgEditWindow *window)
3169 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3170 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3172 if (!GTK_WIDGET_VISIBLE (window))
3175 g_object_ref (window);
3176 text = gtk_clipboard_wait_for_text (selection_clipboard);
3178 if (priv->clipboard_text != NULL) {
3179 g_free (priv->clipboard_text);
3181 priv->clipboard_text = text;
3183 if (GTK_WIDGET_VISIBLE (window)) {
3184 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3186 g_object_unref (window);
3189 static gboolean clipboard_owner_change_idle (gpointer userdata)
3191 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3192 ModestMsgEditWindowPrivate *priv;
3194 gdk_threads_enter ();
3195 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3196 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3198 priv->clipboard_owner_idle = 0;
3199 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3200 gdk_threads_leave ();
3206 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3208 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3209 if (priv->clipboard_owner_idle == 0) {
3210 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3215 subject_field_move_cursor (GtkEntry *entry,
3216 GtkMovementStep step,
3221 if (!GTK_WIDGET_VISIBLE (window))
3224 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3228 update_window_title (ModestMsgEditWindow *window)
3230 ModestMsgEditWindowPrivate *priv = NULL;
3231 const gchar *subject;
3233 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3234 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3235 if (subject == NULL || subject[0] == '\0')
3236 subject = _("mail_va_new_email");
3238 gtk_window_set_title (GTK_WINDOW (window), subject);
3243 subject_field_changed (GtkEditable *editable,
3244 ModestMsgEditWindow *window)
3246 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3247 update_window_title (window);
3248 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3249 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3250 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3254 subject_field_insert_text (GtkEditable *editable,
3256 gint new_text_length,
3258 ModestMsgEditWindow *window)
3260 GString *result = g_string_new ("");
3262 gint result_len = 0;
3263 const gchar *entry_text = NULL;
3266 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3267 old_length = g_utf8_strlen (entry_text, -1);
3269 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3270 gunichar c = g_utf8_get_char_validated (current, 8);
3271 /* Invalid unichar, stop */
3277 result = g_string_append_unichar (result, c);
3281 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3282 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3285 /* Prevent endless recursion */
3286 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3287 g_signal_emit_by_name (editable, "insert-text",
3288 (gpointer) result->str, (gpointer) result->len,
3289 (gpointer) position, (gpointer) window);
3290 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3294 if (result_len + old_length > 1000) {
3295 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3296 dgettext("hildon-common-strings",
3297 "ckdg_ib_maximum_characters_reached"));
3300 g_string_free (result, TRUE);
3304 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3307 ModestMsgEditWindowPrivate *priv = NULL;
3309 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3310 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3312 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3315 gtk_widget_show_all (priv->find_toolbar);
3316 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3318 gtk_widget_hide_all (priv->find_toolbar);
3319 gtk_widget_grab_focus (priv->msg_body);
3325 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3327 GtkTextIter *match_start,
3328 GtkTextIter *match_end)
3330 GtkTextIter end_iter;
3331 gchar *str_casefold;
3334 gchar *range_casefold;
3337 gboolean result = FALSE;
3344 gtk_text_iter_forward_to_end (&end_iter);
3346 str_casefold = g_utf8_casefold (str, -1);
3347 str_chars_n = strlen (str);
3349 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3350 range_casefold = g_utf8_casefold (range_text, -1);
3351 range_chars_n = strlen (range_casefold);
3353 if (range_chars_n < str_chars_n) {
3354 g_free (str_casefold);
3355 g_free (range_text);
3356 g_free (range_casefold);
3360 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3361 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3362 if (!g_utf8_collate (range_subtext, str_casefold)) {
3363 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3365 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3366 match_start, match_end, NULL);
3367 g_free (found_text);
3369 g_free (range_subtext);
3373 g_free (str_casefold);
3374 g_free (range_text);
3375 g_free (range_casefold);
3382 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3383 ModestMsgEditWindow *window)
3385 gchar *current_search = NULL;
3386 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3388 GtkTextIter selection_start, selection_end;
3389 GtkTextIter match_start, match_end;
3390 gboolean continue_search = FALSE;
3392 if (message_is_empty (window)) {
3393 g_free (priv->last_search);
3394 priv->last_search = NULL;
3395 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3399 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3400 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3401 g_free (current_search);
3402 g_free (priv->last_search);
3403 priv->last_search = NULL;
3404 /* Information banner about empty search */
3405 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3409 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3410 continue_search = TRUE;
3412 g_free (priv->last_search);
3413 priv->last_search = g_strdup (current_search);
3416 if (continue_search) {
3417 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3418 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3419 &match_start, &match_end);
3421 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3423 GtkTextIter buffer_start;
3424 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3425 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3426 &match_start, &match_end);
3428 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3431 /* Mark as selected the string found in search */
3433 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3434 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3435 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3437 g_free (priv->last_search);
3438 priv->last_search = NULL;
3440 g_free (current_search);
3444 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3445 ModestMsgEditWindow *window)
3447 GtkToggleAction *toggle;
3448 ModestWindowPrivate *parent_priv;
3449 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3451 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3452 gtk_toggle_action_set_active (toggle, FALSE);
3456 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3458 ModestMsgEditWindowPrivate *priv;
3460 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3465 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3468 ModestMsgEditWindowPrivate *priv;
3470 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3476 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3479 ModestMsgEditWindowPrivate *priv;
3480 TnyHeader *header = NULL;
3482 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3483 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3485 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3486 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3488 if (priv->draft_msg != NULL) {
3489 g_object_unref (priv->draft_msg);
3492 if (draft != NULL) {
3493 g_object_ref (draft);
3494 header = tny_msg_get_header (draft);
3495 if (priv->msg_uid) {
3496 g_free (priv->msg_uid);
3497 priv->msg_uid = NULL;
3499 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3500 if (GTK_WIDGET_REALIZED (window)) {
3501 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3502 gtk_widget_destroy (GTK_WIDGET (window));
3508 priv->draft_msg = draft;
3512 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3513 GtkTextIter *start, GtkTextIter *end,
3516 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3517 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3520 if (tag == NULL) return;
3521 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3522 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3523 replace_with_images (window, priv->images);
3528 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3531 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3533 g_return_if_fail (TNY_IS_MIME_PART (part));
3534 tny_list_prepend (priv->attachments, (GObject *) part);
3535 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3536 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3537 gtk_widget_show_all (priv->attachments_caption);
3538 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3542 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3544 ModestMsgEditWindowPrivate *priv;
3546 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3547 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3549 return priv->msg_uid;
3553 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3554 ModestMsgEditWindowWidgetType widget_type)
3556 ModestMsgEditWindowPrivate *priv;
3558 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3559 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3561 switch (widget_type) {
3562 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3563 return priv->msg_body;
3565 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3566 return priv->to_field;
3568 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3569 return priv->cc_field;
3571 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3572 return priv->bcc_field;
3574 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3575 return priv->subject_field;
3577 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3578 return priv->attachments_view;
3586 remove_tags (WPTextBuffer *buffer)
3588 GtkTextIter start, end;
3590 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3591 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3593 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3597 on_account_removed (TnyAccountStore *account_store,
3598 TnyAccount *account,
3601 /* Do nothing if it's a store account, because we use the
3602 transport to send the messages */
3603 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3604 const gchar *parent_acc = NULL;
3605 const gchar *our_acc = NULL;
3607 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3608 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3609 /* Close this window if I'm showing a message of the removed account */
3610 if (strcmp (parent_acc, our_acc) == 0)
3611 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3616 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3618 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3620 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3626 set_zoom_do_nothing (ModestWindow *window,
3632 get_zoom_do_nothing (ModestWindow *window)