1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
42 #include <modest-account-mgr.h>
43 #include <modest-account-mgr-helpers.h>
45 #include <widgets/modest-msg-edit-window.h>
46 #include <widgets/modest-combo-box.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <wptextview.h>
65 #include <wptextbuffer.h>
66 #include "modest-scroll-area.h"
67 #include "modest-msg-edit-window-ui-dimming.h"
69 #include "modest-hildon-includes.h"
70 #include "widgets/modest-msg-edit-window-ui.h"
71 #include <libgnomevfs/gnome-vfs-mime.h>
72 #include <modest-utils.h>
73 #include "modest-maemo-utils.h"
76 #define DEFAULT_FONT_SIZE 3
77 #define DEFAULT_FONT 2
78 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
79 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
80 #define DEFAULT_MAIN_VBOX_SPACING 6
81 #define SUBJECT_MAX_LENGTH 1000
82 #define IMAGE_MAX_WIDTH 560
83 #define DEFAULT_FONT_SCALE 1.5
85 static gboolean is_wp_text_buffer_started = FALSE;
87 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
88 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
89 static void modest_msg_edit_window_finalize (GObject *obj);
91 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
92 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
93 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
95 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
96 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
97 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
98 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
99 GtkTextIter *start, GtkTextIter *end,
101 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
102 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
103 static void subject_field_insert_text (GtkEditable *editable,
105 gint new_text_length,
107 ModestMsgEditWindow *window);
108 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
110 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
112 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
114 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
115 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
116 GdkEventWindowState *event,
118 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
119 ModestRecptEditor *editor);
120 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
121 ModestMsgEditWindow *window);
123 /* ModestWindow methods implementation */
124 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
125 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
126 gboolean show_toolbar);
127 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
129 ModestMsgEditWindow *window);
130 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
131 static void subject_field_move_cursor (GtkEntry *entry,
132 GtkMovementStep step,
136 static void update_window_title (ModestMsgEditWindow *window);
139 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
140 ModestMsgEditWindow *window);
141 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
142 ModestMsgEditWindow *window);
143 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
145 GtkTextIter *match_start,
146 GtkTextIter *match_end);
148 static void remove_tags (WPTextBuffer *buffer);
150 static void on_account_removed (TnyAccountStore *account_store,
154 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
155 static void set_zoom_do_nothing (ModestWindow *window, gdouble zoom);
156 static gdouble get_zoom_do_nothing (ModestWindow *window);
158 static void init_window (ModestMsgEditWindow *obj);
160 gboolean scroll_drag_timeout (gpointer userdata);
161 static void correct_scroll (ModestMsgEditWindow *w);
162 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
163 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
164 ModestMsgEditWindow *userdata);
165 static void text_buffer_mark_set (GtkTextBuffer *buffer,
168 ModestMsgEditWindow *userdata);
169 static void vadj_changed (GtkAdjustment *adj,
170 ModestMsgEditWindow *window);
172 static void DEBUG_BUFFER (WPTextBuffer *buffer)
176 g_debug ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
178 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
179 while (!gtk_text_iter_is_end (&iter)) {
180 GString *output = g_string_new ("");
181 GSList *toggled_tags;
184 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
185 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
186 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
187 GtkTextTag *tag = (GtkTextTag *) node->data;
189 g_object_get (G_OBJECT (tag), "name", &name, NULL);
190 output = g_string_append (output, name);
191 g_string_append (output, " ");
193 output = g_string_append (output, "] OPENED [ ");
194 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
195 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
196 GtkTextTag *tag = (GtkTextTag *) node->data;
198 g_object_get (G_OBJECT (tag), "name", &name, NULL);
199 output = g_string_append (output, name);
200 g_string_append (output, " ");
202 output = g_string_append (output, "]\n");
203 g_debug ("%s", output->str);
204 g_string_free (output, TRUE);
205 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
207 g_debug ("END BUFFER");
212 /* static gboolean */
213 /* on_key_pressed (GtkWidget *self, */
214 /* GdkEventKey *event, */
215 /* gpointer user_data); */
217 /* list my signals */
224 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
225 struct _ModestMsgEditWindowPrivate {
228 GtkWidget *header_box;
230 ModestPairList *from_field_protos;
231 GtkWidget *from_field;
232 gchar *original_account_name;
236 GtkWidget *bcc_field;
237 GtkWidget *subject_field;
238 GtkWidget *attachments_view;
239 GtkWidget *priority_icon;
240 GtkWidget *add_attachment_button;
242 GtkWidget *cc_caption;
243 GtkWidget *bcc_caption;
244 gboolean update_caption_visibility;
245 GtkWidget *attachments_caption;
247 GtkTextBuffer *text_buffer;
249 GtkWidget *font_size_toolitem;
250 GtkWidget *font_face_toolitem;
251 GtkWidget *font_color_button;
252 GSList *font_items_group;
253 GtkWidget *font_tool_button_label;
254 GSList *size_items_group;
255 GtkWidget *size_tool_button_label;
257 GtkWidget *find_toolbar;
260 GtkWidget *font_dialog;
263 guint scroll_drag_timeout_id;
267 TnyList *attachments;
272 TnyHeaderFlags priority_flags;
274 gboolean can_undo, can_redo;
275 gulong clipboard_change_handler_id;
276 gulong default_clipboard_change_handler_id;
277 gulong account_removed_handler_id;
278 guint clipboard_owner_idle;
279 gchar *clipboard_text;
290 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
291 MODEST_TYPE_MSG_EDIT_WINDOW, \
292 ModestMsgEditWindowPrivate))
294 static GtkWindowClass *parent_class = NULL;
296 /* uncomment the following if you have defined any signals */
297 /* static guint signals[LAST_SIGNAL] = {0}; */
300 modest_msg_edit_window_get_type (void)
302 static GType my_type = 0;
304 static const GTypeInfo my_info = {
305 sizeof(ModestMsgEditWindowClass),
306 NULL, /* base init */
307 NULL, /* base finalize */
308 (GClassInitFunc) modest_msg_edit_window_class_init,
309 NULL, /* class finalize */
310 NULL, /* class data */
311 sizeof(ModestMsgEditWindow),
313 (GInstanceInitFunc) modest_msg_edit_window_init,
316 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
317 "ModestMsgEditWindow",
325 save_state (ModestWindow *self)
327 modest_widget_memory_save (modest_runtime_get_conf(),
328 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
333 restore_settings (ModestMsgEditWindow *self)
335 ModestConf *conf = NULL;
337 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
339 conf = modest_runtime_get_conf ();
340 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
341 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
342 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
343 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL));
344 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
345 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu");
346 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
347 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
349 /* set initial state of cc and bcc */
350 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
351 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
352 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
353 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
354 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
355 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
357 /* Dim at start clipboard actions */
358 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
359 gtk_action_set_sensitive (action, FALSE);
360 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
361 gtk_action_set_sensitive (action, FALSE);
362 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
363 gtk_action_set_sensitive (action, FALSE);
365 modest_widget_memory_restore (conf,
366 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
371 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
373 GObjectClass *gobject_class;
374 ModestWindowClass *modest_window_class;
375 gobject_class = (GObjectClass*) klass;
376 modest_window_class = (ModestWindowClass*) klass;
378 parent_class = g_type_class_peek_parent (klass);
379 gobject_class->finalize = modest_msg_edit_window_finalize;
381 modest_window_class->set_zoom_func = set_zoom_do_nothing;
382 modest_window_class->get_zoom_func = get_zoom_do_nothing;
383 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
384 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
385 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
386 modest_window_class->save_state_func = save_state;
387 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
389 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
393 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
395 ModestMsgEditWindowPrivate *priv;
396 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
398 priv->msg_body = NULL;
400 priv->from_field = NULL;
401 priv->to_field = NULL;
402 priv->cc_field = NULL;
403 priv->bcc_field = NULL;
404 priv->subject_field = NULL;
405 priv->attachments = TNY_LIST (tny_simple_list_new ());
406 priv->images = TNY_LIST (tny_simple_list_new ());
407 priv->images_size = 0;
408 priv->images_count = 0;
411 priv->cc_caption = NULL;
412 priv->bcc_caption = NULL;
413 priv->update_caption_visibility = FALSE;
415 priv->priority_flags = 0;
417 priv->find_toolbar = NULL;
418 priv->last_search = NULL;
420 priv->draft_msg = NULL;
421 priv->outbox_msg = NULL;
422 priv->msg_uid = NULL;
423 priv->references = NULL;
424 priv->in_reply_to = NULL;
426 priv->can_undo = FALSE;
427 priv->can_redo = FALSE;
428 priv->clipboard_change_handler_id = 0;
429 priv->default_clipboard_change_handler_id = 0;
430 priv->account_removed_handler_id = 0;
431 priv->clipboard_owner_idle = 0;
432 priv->clipboard_text = NULL;
435 priv->scroll_drag_timeout_id = 0;
436 priv->last_upper = 0.0;
438 priv->font_dialog = NULL;
440 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
441 GTK_WINDOW(obj),"applications_email_editor");
443 if (!is_wp_text_buffer_started) {
444 is_wp_text_buffer_started = TRUE;
445 wp_text_buffer_library_init ();
450 hildon_program_add_window (hildon_program_get_instance(),
455 /* FIXME: this is a dup from the one in gtk/ */
458 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
460 static ModestPairList*
461 get_transports (void)
463 GSList *transports = NULL;
465 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
466 GSList *accounts = modest_account_mgr_account_names (account_mgr,
467 TRUE /* only enabled accounts. */);
469 GSList *cursor = accounts;
471 gchar *account_name = cursor->data;
472 gchar *from_string = NULL;
474 from_string = modest_account_mgr_get_from_string (account_mgr,
478 if (from_string && account_name) {
479 gchar *name = account_name;
480 ModestPair *pair = modest_pair_new ((gpointer) name,
481 (gpointer) from_string , TRUE);
482 transports = g_slist_prepend (transports, pair);
485 cursor = cursor->next;
487 g_slist_free (accounts); /* only free the accounts, not the elements,
488 * because they are used in the pairlist */
492 static void window_focus (GtkWindow *window,
496 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
500 scroll_drag_timeout (gpointer userdata)
502 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
503 ModestMsgEditWindowPrivate *priv;
505 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
507 correct_scroll_without_drag_check (win, TRUE);
509 priv->scroll_drag_timeout_id = 0;
515 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
517 ModestMsgEditWindowPrivate *priv;
520 GdkRectangle rectangle;
526 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
528 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
531 insert = gtk_text_buffer_get_insert (priv->text_buffer);
532 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
534 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
535 vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll));
536 offset = priv->msg_body->allocation.y;
538 new_value = vadj->value;
540 if ((offset + rectangle.y + rectangle.height) >
541 ((gint) (vadj->value +vadj->page_size))) {
542 new_value = (offset + rectangle.y) - vadj->page_size * 0.25;
543 if (new_value > vadj->upper - vadj->page_size)
544 new_value = vadj->upper - vadj->page_size;
545 } else if ((offset + rectangle.y) < ((gint) vadj->value)) {
546 new_value = (offset + rectangle.y - vadj->page_size * 0.75);
547 if (((gint) (new_value + vadj->page_size)) < (offset + rectangle.y + rectangle.height))
548 new_value = offset + rectangle.y + rectangle.height - (gint) vadj->page_size;
551 if (new_value > vadj->value)
552 new_value = vadj->value;
555 if (vadj->value != new_value) {
556 g_signal_emit_by_name (GTK_TEXT_VIEW(priv->msg_body)->layout,
558 vadj->value = new_value;
559 gtk_adjustment_value_changed (vadj);
560 /* invalidate body */
561 window = gtk_widget_get_parent_window (priv->msg_body);
563 gdk_window_invalidate_rect (window, NULL, TRUE);
569 correct_scroll (ModestMsgEditWindow *w)
571 ModestMsgEditWindowPrivate *priv;
573 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
574 if (gtk_grab_get_current () == priv->msg_body) {
575 if (priv->scroll_drag_timeout_id == 0) {
576 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
582 correct_scroll_without_drag_check (w, TRUE);
586 text_buffer_end_user_action (GtkTextBuffer *buffer,
587 ModestMsgEditWindow *userdata)
590 correct_scroll (userdata);
594 text_buffer_mark_set (GtkTextBuffer *buffer,
597 ModestMsgEditWindow *userdata)
599 gtk_text_buffer_begin_user_action (buffer);
600 gtk_text_buffer_end_user_action (buffer);
604 cut_clipboard_check (GtkTextView *text_view,
607 GtkTextBuffer *buffer;
609 buffer = gtk_text_view_get_buffer (text_view);
610 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
611 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
616 copy_clipboard_check (GtkTextView *text_view,
619 GtkTextBuffer *buffer;
621 buffer = gtk_text_view_get_buffer (text_view);
622 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
623 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
628 vadj_changed (GtkAdjustment *adj,
629 ModestMsgEditWindow *window)
631 ModestMsgEditWindowPrivate *priv;
633 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
635 if (priv->last_upper != adj->upper) {
636 priv->last_upper = adj->upper;
637 correct_scroll (window);
642 attachment_deleted (ModestAttachmentsView *attachments_view,
645 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
650 connect_signals (ModestMsgEditWindow *obj)
652 ModestMsgEditWindowPrivate *priv;
654 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
656 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
657 G_CALLBACK (text_buffer_refresh_attributes), obj);
658 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
659 G_CALLBACK (text_buffer_can_undo), obj);
660 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
661 G_CALLBACK (text_buffer_can_redo), obj);
662 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
663 G_CALLBACK (body_changed), obj);
664 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
665 G_CALLBACK (body_changed), obj);
666 g_signal_connect (G_OBJECT (obj), "window-state-event",
667 G_CALLBACK (modest_msg_edit_window_window_state_event),
669 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
670 G_CALLBACK (text_buffer_end_user_action), obj);
671 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
672 G_CALLBACK (text_buffer_mark_set), obj);
673 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
674 G_CALLBACK (text_buffer_apply_tag), obj);
675 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
676 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
677 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
678 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
679 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
680 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
682 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
683 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
685 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
686 G_CALLBACK (msg_body_focus), obj);
687 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
688 G_CALLBACK (msg_body_focus), obj);
689 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
690 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
691 "changed", G_CALLBACK (recpt_field_changed), obj);
692 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
693 "changed", G_CALLBACK (recpt_field_changed), obj);
694 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
695 "changed", G_CALLBACK (recpt_field_changed), obj);
696 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
697 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
698 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
700 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
701 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
703 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
705 G_CALLBACK (vadj_changed),
708 priv->clipboard_change_handler_id =
709 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
710 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
711 priv->default_clipboard_change_handler_id =
712 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
713 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
715 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
716 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
717 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
721 init_window (ModestMsgEditWindow *obj)
723 GtkWidget *from_caption, *to_caption, *subject_caption;
724 GtkWidget *main_vbox;
725 ModestMsgEditWindowPrivate *priv;
726 GtkActionGroup *action_group;
727 ModestWindowPrivate *parent_priv;
728 GdkPixbuf *window_icon = NULL;
729 GError *error = NULL;
731 GtkSizeGroup *size_group;
732 GtkWidget *subject_box;
733 GtkWidget *attachment_icon;
734 GtkWidget *window_box;
735 #if (GTK_MINOR_VERSION >= 10)
736 GdkAtom deserialize_type;
738 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
739 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
741 parent_priv->ui_manager = gtk_ui_manager_new();
742 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
743 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
745 /* Add common actions */
746 gtk_action_group_add_actions (action_group,
747 modest_msg_edit_action_entries,
748 G_N_ELEMENTS (modest_msg_edit_action_entries),
750 gtk_action_group_add_toggle_actions (action_group,
751 modest_msg_edit_toggle_action_entries,
752 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
754 gtk_action_group_add_radio_actions (action_group,
755 modest_msg_edit_alignment_radio_action_entries,
756 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
758 G_CALLBACK (modest_ui_actions_on_change_justify),
760 gtk_action_group_add_radio_actions (action_group,
761 modest_msg_edit_priority_action_entries,
762 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
764 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
766 gtk_action_group_add_radio_actions (action_group,
767 modest_msg_edit_file_format_action_entries,
768 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
769 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
770 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
772 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
773 g_object_unref (action_group);
775 /* Load the UI definition */
776 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
779 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
780 g_clear_error (&error);
783 /* Add accelerators */
784 gtk_window_add_accel_group (GTK_WINDOW (obj),
785 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
787 parent_priv->menubar = NULL;
789 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
791 /* Note: This ModestPairList* must exist for as long as the combo
792 * that uses it, because the ModestComboBox uses the ID opaquely,
793 * so it can't know how to manage its memory. */
794 priv->from_field = modest_combo_box_new (NULL, g_str_equal);
796 priv->to_field = modest_recpt_editor_new ();
797 priv->cc_field = modest_recpt_editor_new ();
798 priv->bcc_field = modest_recpt_editor_new ();
799 subject_box = gtk_hbox_new (FALSE, 0);
800 priv->priority_icon = gtk_image_new ();
801 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
802 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
803 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
804 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
805 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
806 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
807 priv->add_attachment_button = gtk_button_new ();
808 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
809 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
810 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
811 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
812 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
813 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
814 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
815 priv->attachments_view = modest_attachments_view_new (NULL);
817 priv->header_box = gtk_vbox_new (FALSE, 0);
819 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
820 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
821 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
822 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
823 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
824 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
825 g_object_unref (size_group);
827 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
828 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
829 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
830 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
831 gtk_size_group_add_widget (size_group, priv->subject_field);
832 gtk_size_group_add_widget (size_group, priv->attachments_view);
833 g_object_unref (size_group);
835 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
836 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
837 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
838 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
839 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
840 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
841 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
844 priv->msg_body = wp_text_view_new ();
845 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
846 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
847 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
848 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
849 #if (GTK_MINOR_VERSION >= 10)
850 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
851 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
853 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
854 deserialize_type, TRUE);
856 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
858 priv->find_toolbar = hildon_find_toolbar_new (NULL);
859 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
861 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
863 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
864 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
865 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
866 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
868 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
870 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
871 priv->frame = gtk_frame_new (NULL);
872 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
874 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
875 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
876 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
878 window_box = gtk_vbox_new (FALSE, 0);
879 gtk_container_add (GTK_CONTAINER(obj), window_box);
881 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
883 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
885 /* Set window icon */
886 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
888 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
889 g_object_unref (window_icon);
894 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
896 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
898 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
899 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
900 priv->clipboard_change_handler_id))
901 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
902 priv->clipboard_change_handler_id);
903 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
904 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
905 priv->default_clipboard_change_handler_id))
906 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
907 priv->default_clipboard_change_handler_id);
909 if (priv->account_removed_handler_id &&
910 g_signal_handler_is_connected (modest_runtime_get_account_store (),
911 priv->account_removed_handler_id))
912 g_signal_handler_disconnect(modest_runtime_get_account_store (),
913 priv->account_removed_handler_id);
917 modest_msg_edit_window_finalize (GObject *obj)
919 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
921 /* Sanity check: shouldn't be needed, the window mgr should
922 call this function before */
923 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
925 if (priv->font_dialog != NULL) {
926 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
929 if (priv->clipboard_text != NULL) {
930 g_free (priv->clipboard_text);
931 priv->clipboard_text = NULL;
934 if (priv->draft_msg != NULL) {
935 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
936 if (TNY_IS_HEADER (header)) {
937 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
938 modest_window_mgr_unregister_header (mgr, header);
940 g_object_unref (priv->draft_msg);
941 priv->draft_msg = NULL;
943 if (priv->outbox_msg != NULL) {
944 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
945 if (TNY_IS_HEADER (header)) {
946 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
947 modest_window_mgr_unregister_header (mgr, header);
949 g_object_unref (priv->outbox_msg);
950 priv->outbox_msg = NULL;
952 if (priv->scroll_drag_timeout_id > 0) {
953 g_source_remove (priv->scroll_drag_timeout_id);
954 priv->scroll_drag_timeout_id = 0;
956 if (priv->clipboard_owner_idle > 0) {
957 g_source_remove (priv->clipboard_owner_idle);
958 priv->clipboard_owner_idle = 0;
960 if (priv->original_account_name)
961 g_free (priv->original_account_name);
962 g_free (priv->msg_uid);
963 g_free (priv->references);
964 g_free (priv->in_reply_to);
965 g_free (priv->last_search);
966 g_slist_free (priv->font_items_group);
967 g_slist_free (priv->size_items_group);
968 g_object_unref (priv->attachments);
969 g_object_unref (priv->images);
971 /* This had to stay alive for as long as the combobox that used it: */
972 modest_pair_list_free (priv->from_field_protos);
974 G_OBJECT_CLASS(parent_class)->finalize (obj);
978 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
980 GdkPixbufLoader *loader;
986 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
988 if (loader == NULL) {
994 tny_stream_reset (TNY_STREAM (stream));
995 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
996 GError *error = NULL;
997 unsigned char read_buffer[128];
999 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1001 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1008 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1010 g_object_ref (pixbuf);
1011 gdk_pixbuf_loader_close (loader, NULL);
1012 g_object_unref (loader);
1017 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1018 GdkPixbuf *new_pixbuf;
1020 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1021 gdk_pixbuf_get_width (pixbuf);
1022 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1023 g_object_unref (pixbuf);
1024 pixbuf = new_pixbuf;
1028 *stream_size = size;
1034 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1036 ModestMsgEditWindowPrivate *priv;
1039 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1041 for (iter = tny_list_create_iterator (attachments);
1042 !tny_iterator_is_done (iter);
1043 tny_iterator_next (iter)) {
1044 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1045 const gchar *cid = tny_mime_part_get_content_id (part);
1046 const gchar *mime_type = tny_mime_part_get_content_type (part);
1047 if ((cid != NULL)&&(mime_type != NULL)) {
1048 guint64 stream_size;
1049 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1050 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1053 g_object_unref (stream);
1055 if (pixbuf != NULL) {
1056 priv->images_count ++;
1057 priv->images_size += stream_size;
1058 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1059 g_object_unref (pixbuf);
1062 g_object_unref (part);
1064 g_object_unref (iter);
1068 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1070 TnyMimePart *parent = NULL;
1071 const gchar *content_type = NULL;
1072 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1074 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1076 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1077 parent = g_object_ref (msg);
1078 } else if (content_type && !g_ascii_strcasecmp (content_type, "multipart/mixed")) {
1079 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1082 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1083 iter = tny_list_create_iterator (parts);
1084 while (!tny_iterator_is_done (iter)) {
1086 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1087 content_type = tny_mime_part_get_content_type (part);
1088 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1092 g_object_unref (part);
1094 tny_iterator_next (iter);
1096 g_object_unref (iter);
1097 g_object_unref (parts);
1100 if (parent != NULL) {
1101 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1104 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1105 iter = tny_list_create_iterator (parts);
1106 while (!tny_iterator_is_done (iter)) {
1108 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1109 content_type = tny_mime_part_get_content_type (part);
1110 if (content_type && g_str_has_prefix (content_type, "image/")) {
1111 tny_list_prepend (priv->images, (GObject *) part);
1113 g_object_unref (part);
1114 tny_iterator_next (iter);
1116 g_object_unref (iter);
1117 g_object_unref (parts);
1118 g_object_unref (parent);
1123 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1126 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1128 for (iter = tny_list_create_iterator (attachments) ;
1129 !tny_iterator_is_done (iter);
1130 tny_iterator_next (iter)) {
1131 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1132 const gchar *cid = tny_mime_part_get_content_id (part);
1134 char *invalid = NULL;
1135 gint int_cid = strtol (cid, &invalid, 10);
1136 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1137 priv->next_cid = int_cid + 1;
1140 g_object_unref (part);
1142 g_object_unref (iter);
1146 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1149 gchar *to, *cc, *bcc, *subject;
1151 ModestMsgEditWindowPrivate *priv;
1153 TnyHeaderFlags priority_flags;
1154 TnyFolder *msg_folder;
1155 gboolean is_html = FALSE;
1157 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1158 g_return_if_fail (TNY_IS_MSG (msg));
1160 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1162 header = tny_msg_get_header (msg);
1163 to = tny_header_dup_to (header);
1164 cc = tny_header_dup_cc (header);
1165 bcc = tny_header_dup_bcc (header);
1166 subject = tny_header_dup_subject (header);
1167 priority_flags = tny_header_get_priority (header);
1170 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1172 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1173 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1174 gtk_widget_show (priv->cc_caption);
1175 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1176 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1177 gtk_widget_hide (priv->cc_caption);
1180 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1181 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1182 gtk_widget_show (priv->bcc_caption);
1183 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1184 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1185 gtk_widget_hide (priv->bcc_caption);
1188 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1189 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1191 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1193 update_window_title (self);
1195 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1196 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1198 if ((body == NULL)||(body[0] == '\0')) {
1200 body = modest_text_utils_convert_to_html ("");
1203 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1204 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1207 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1210 /* Add attachments to the view */
1211 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1212 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1213 if (tny_list_get_length (priv->attachments) == 0) {
1214 gtk_widget_hide (priv->attachments_caption);
1216 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1217 gtk_widget_show_all (priv->attachments_caption);
1219 get_related_images (self, msg);
1220 update_next_cid (self, priv->attachments);
1221 update_next_cid (self, priv->images);
1222 replace_with_images (self, priv->images);
1224 if (preserve_is_rich && !is_html) {
1225 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1226 /* Get the default format required from configuration */
1227 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1228 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1231 /* Set the default focus depending on having already a To: field or not */
1232 if ((!to)||(*to == '\0')) {
1233 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1235 gtk_widget_grab_focus (priv->msg_body);
1238 /* TODO: lower priority, select in the From: combo to the
1239 value that comes from msg <- not sure, should it be
1242 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1244 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1245 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1247 modest_msg_edit_window_set_modified (self, FALSE);
1249 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1250 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1251 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1252 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1254 if (priv->msg_uid) {
1255 g_free (priv->msg_uid);
1256 priv->msg_uid = NULL;
1259 /* we should set a reference to the incoming message if it is a draft */
1260 msg_folder = tny_msg_get_folder (msg);
1262 if (modest_tny_folder_is_local_folder (msg_folder)) {
1263 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1264 if (type == TNY_FOLDER_TYPE_INVALID)
1265 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1267 if (type == TNY_FOLDER_TYPE_DRAFTS)
1268 priv->draft_msg = g_object_ref(msg);
1269 if (type == TNY_FOLDER_TYPE_OUTBOX)
1270 priv->outbox_msg = g_object_ref(msg);
1271 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1273 g_object_unref (msg_folder);
1283 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1286 GList *item_children, *node;
1287 GtkWidget *bin_child;
1289 bin_child = gtk_bin_get_child (GTK_BIN(item));
1291 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1293 for (node = item_children; node != NULL; node = g_list_next (node)) {
1294 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1295 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1298 g_list_free (item_children);
1302 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1305 GList *item_children, *node;
1307 box = gtk_bin_get_child (GTK_BIN (item));
1308 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1309 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1311 for (node = item_children; node != NULL; node = g_list_next (node)) {
1312 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1313 if (GTK_IS_TOGGLE_BUTTON (node->data))
1314 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1315 else if (GTK_IS_BUTTON (node->data))
1316 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1318 g_list_free (item_children);
1323 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1325 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1326 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1327 GtkWidget *placeholder;
1328 GtkWidget *tool_item;
1333 GtkWidget *sizes_menu;
1334 GtkWidget *fonts_menu;
1335 GSList *radio_group = NULL;
1336 GSList *node = NULL;
1340 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1341 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1343 /* Font color placeholder */
1344 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1345 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1348 tool_item = GTK_WIDGET (gtk_tool_item_new ());
1349 priv->font_color_button = hildon_color_button_new ();
1350 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1351 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1352 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
1353 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1354 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1355 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1356 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1358 G_CALLBACK (modest_msg_edit_window_color_button_change),
1361 /* Font size and face placeholder */
1362 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1363 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1365 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1366 priv->size_tool_button_label = gtk_label_new (NULL);
1367 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1368 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1369 size_text,"</span>", NULL);
1370 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1372 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1373 sizes_menu = gtk_menu_new ();
1374 priv->size_items_group = NULL;
1376 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1377 GtkWidget *size_menu_item;
1379 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1380 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1381 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1382 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1383 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1384 gtk_widget_show (size_menu_item);
1386 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1390 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1391 GtkWidget *item = (GtkWidget *) node->data;
1392 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1396 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1397 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1398 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1399 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1400 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1401 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1402 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1403 priv->font_size_toolitem = tool_item;
1406 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1407 priv->font_tool_button_label = gtk_label_new (NULL);
1408 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1409 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1411 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1412 fonts_menu = gtk_menu_new ();
1413 priv->font_items_group = NULL;
1415 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1416 GtkWidget *font_menu_item;
1417 GtkWidget *child_label;
1419 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1420 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1421 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1422 wp_get_font_name (font_index), "</span>", NULL);
1423 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1426 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1427 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1428 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1429 gtk_widget_show (font_menu_item);
1431 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1434 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1435 GtkWidget *item = (GtkWidget *) node->data;
1436 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1439 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1440 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1441 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1442 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1443 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1444 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1445 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1446 priv->font_face_toolitem = tool_item;
1448 /* Set expand and homogeneous for remaining items */
1449 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1450 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1451 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1452 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1453 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1454 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1455 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1456 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1457 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1459 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1460 will not show the tool items added to the placeholders) */
1461 gtk_widget_show_all (parent_priv->toolbar);
1463 /* Set the no show all *after* showing all items. We do not
1464 want the toolbar to be shown with a show all because it
1465 could go agains the gconf setting regarding showing or not
1466 the toolbar of the editor window */
1467 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1473 modest_msg_edit_window_new (TnyMsg *msg,
1474 const gchar *account_name,
1475 const gchar *mailbox, /* ignored */
1476 gboolean preserve_is_rich)
1479 ModestWindowPrivate *parent_priv;
1480 ModestMsgEditWindowPrivate *priv;
1481 ModestDimmingRulesGroup *menu_rules_group = NULL;
1482 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1483 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1484 ModestWindowMgr *mgr = NULL;
1486 g_return_val_if_fail (msg, NULL);
1487 g_return_val_if_fail (account_name, NULL);
1489 mgr = modest_runtime_get_window_mgr ();
1491 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1493 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1494 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1496 /* Menubar. Update the state of some toggles */
1497 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1498 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1499 priv->from_field_protos = get_transports ();
1500 modest_combo_box_set_pair_list (MODEST_COMBO_BOX (priv->from_field), priv->from_field_protos);
1501 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), (gpointer) account_name);
1502 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1503 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1506 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1508 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1510 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1512 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1514 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1515 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1516 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1517 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1518 /* Add common dimming rules */
1519 modest_dimming_rules_group_add_rules (menu_rules_group,
1520 modest_msg_edit_window_menu_dimming_entries,
1521 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1522 MODEST_WINDOW (obj));
1523 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1524 modest_msg_edit_window_toolbar_dimming_entries,
1525 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1526 MODEST_WINDOW (obj));
1527 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1528 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1529 MODEST_WINDOW (obj));
1530 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1531 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1532 MODEST_WINDOW (obj));
1533 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1534 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1535 MODEST_WINDOW (obj));
1536 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1537 modest_msg_edit_window_clipboard_dimming_entries,
1538 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1539 MODEST_WINDOW (obj));
1540 /* Insert dimming rules group for this window */
1541 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1542 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1543 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1544 /* Checks the dimming rules */
1545 g_object_unref (menu_rules_group);
1546 g_object_unref (toolbar_rules_group);
1547 g_object_unref (clipboard_rules_group);
1548 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1550 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1552 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1553 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1554 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1555 priv->update_caption_visibility = TRUE;
1557 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1559 /* Track account-removed signal, this window should be closed
1560 in the case we're creating a mail associated to the account
1562 priv->account_removed_handler_id =
1563 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1565 G_CALLBACK(on_account_removed),
1568 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1570 return (ModestWindow*) obj;
1574 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1576 GString **string_buffer = (GString **) user_data;
1578 *string_buffer = g_string_append (*string_buffer, buffer);
1584 * @result: A new string which should be freed with g_free().
1587 get_formatted_data (ModestMsgEditWindow *edit_window)
1589 ModestMsgEditWindowPrivate *priv;
1590 GString *string_buffer = g_string_new ("");
1592 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1594 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1596 modest_text_utils_hyperlinkify (string_buffer);
1598 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1600 return g_string_free (string_buffer, FALSE);
1605 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1608 const gchar *account_name;
1609 ModestMsgEditWindowPrivate *priv;
1610 TnyIterator *att_iter;
1612 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1614 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1616 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1617 g_return_val_if_fail (account_name, NULL);
1620 /* don't free these (except from) */
1621 data = g_slice_new0 (MsgData);
1622 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1623 account_name, NULL);
1624 data->account_name = g_strdup (account_name);
1625 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1626 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1627 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1628 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1629 data->references = g_strdup (priv->references);
1630 data->in_reply_to = g_strdup (priv->in_reply_to);
1631 if (priv->draft_msg) {
1632 data->draft_msg = g_object_ref (priv->draft_msg);
1633 } else if (priv->outbox_msg) {
1634 data->draft_msg = g_object_ref (priv->outbox_msg);
1636 data->draft_msg = NULL;
1639 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1641 gtk_text_buffer_get_bounds (buf, &b, &e);
1642 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1644 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1645 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1647 data->html_body = NULL;
1649 /* deep-copy the data */
1650 att_iter = tny_list_create_iterator (priv->attachments);
1651 data->attachments = NULL;
1652 while (!tny_iterator_is_done (att_iter)) {
1653 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 data->attachments = g_list_append (data->attachments,
1662 tny_iterator_next (att_iter);
1664 g_object_unref (att_iter);
1666 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1667 att_iter = tny_list_create_iterator (priv->images);
1668 data->images = NULL;
1669 while (!tny_iterator_is_done (att_iter)) {
1670 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1672 if (!(TNY_IS_MIME_PART(part))) {
1673 g_warning ("strange data in attachment list");
1674 g_object_unref (part);
1675 tny_iterator_next (att_iter);
1678 cid = tny_mime_part_get_content_id (part);
1680 gchar *image_tag_id;
1681 GtkTextTag *image_tag;
1683 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1684 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1685 g_free (image_tag_id);
1687 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1689 ((gtk_text_iter_has_tag (&iter, image_tag))||
1690 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1691 data->images = g_list_append (data->images,
1692 g_object_ref (part));
1694 g_object_unref (part);
1695 tny_iterator_next (att_iter);
1697 g_object_unref (att_iter);
1699 data->priority_flags = priv->priority_flags;
1706 unref_gobject (GObject *obj, gpointer data)
1708 if (!G_IS_OBJECT(obj))
1710 g_object_unref (obj);
1714 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1717 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1725 g_free (data->from);
1726 g_free (data->subject);
1727 g_free (data->plain_body);
1728 g_free (data->html_body);
1729 g_free (data->account_name);
1730 g_free (data->in_reply_to);
1731 g_free (data->references);
1733 if (data->draft_msg != NULL) {
1734 g_object_unref (data->draft_msg);
1735 data->draft_msg = NULL;
1738 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1739 g_list_free (data->attachments);
1740 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1741 g_list_free (data->images);
1743 g_slice_free (MsgData, data);
1747 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1749 guint64 *parts_size)
1751 ModestMsgEditWindowPrivate *priv;
1753 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1755 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1757 /* TODO: add images */
1758 *parts_size += priv->images_size;
1759 *parts_count += priv->images_count;
1764 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1767 ModestMsgEditWindowPrivate *priv = NULL;
1768 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1770 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1772 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1774 return MODEST_MSG_EDIT_FORMAT_HTML;
1776 return MODEST_MSG_EDIT_FORMAT_TEXT;
1780 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1781 ModestMsgEditFormat format)
1783 ModestMsgEditWindowPrivate *priv;
1785 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1786 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1789 case MODEST_MSG_EDIT_FORMAT_HTML:
1790 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1792 case MODEST_MSG_EDIT_FORMAT_TEXT:
1793 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1796 g_return_if_reached ();
1800 ModestMsgEditFormatState *
1801 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1803 ModestMsgEditFormatState *format_state = NULL;
1804 ModestMsgEditWindowPrivate *priv;
1805 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1807 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1808 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1810 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1812 format_state = g_new0 (ModestMsgEditFormatState, 1);
1813 format_state->bold = buffer_format->bold&0x1;
1814 format_state->italics = buffer_format->italic&0x1;
1815 format_state->bullet = buffer_format->bullet&0x1;
1816 format_state->color = buffer_format->color;
1817 format_state->font_size = buffer_format->font_size;
1818 format_state->font_family = wp_get_font_name (buffer_format->font);
1819 format_state->justification = buffer_format->justification;
1820 g_free (buffer_format);
1822 return format_state;
1827 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1828 const ModestMsgEditFormatState *format_state)
1830 ModestMsgEditWindowPrivate *priv;
1831 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1832 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1833 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1834 g_return_if_fail (format_state != NULL);
1836 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1837 gtk_widget_grab_focus (priv->msg_body);
1838 buffer_format->bold = (format_state->bold != FALSE);
1839 buffer_format->italic = (format_state->italics != FALSE);
1840 buffer_format->color = format_state->color;
1841 buffer_format->font_size = format_state->font_size;
1842 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1843 buffer_format->justification = format_state->justification;
1844 buffer_format->bullet = format_state->bullet;
1846 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1848 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1849 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1850 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1851 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1852 buffer_format->cs.font = (buffer_format->font != current_format->font);
1853 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1854 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1856 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1857 if (buffer_format->cs.bold) {
1858 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1859 GINT_TO_POINTER (buffer_format->bold&0x1));
1861 if (buffer_format->cs.italic) {
1862 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1863 GINT_TO_POINTER (buffer_format->italic&0x1));
1865 if (buffer_format->cs.color) {
1866 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1867 GINT_TO_POINTER (&(buffer_format->color)));
1869 if (buffer_format->cs.font_size) {
1870 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1871 GINT_TO_POINTER (buffer_format->font_size));
1873 if (buffer_format->cs.justification) {
1874 switch (buffer_format->justification) {
1875 case GTK_JUSTIFY_LEFT:
1876 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1877 GINT_TO_POINTER(TRUE));
1879 case GTK_JUSTIFY_CENTER:
1880 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1881 GINT_TO_POINTER(TRUE));
1883 case GTK_JUSTIFY_RIGHT:
1884 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1885 GINT_TO_POINTER(TRUE));
1892 if (buffer_format->cs.font) {
1893 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1894 GINT_TO_POINTER (buffer_format->font));
1896 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1897 if (buffer_format->cs.bullet) {
1898 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1899 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1901 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1903 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1905 g_free (buffer_format);
1906 g_free (current_format);
1908 /* Check dimming rules */
1909 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1910 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1914 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1916 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1918 ModestWindowPrivate *parent_priv;
1919 ModestMsgEditWindowPrivate *priv;
1920 GtkWidget *new_size_menuitem;
1921 GtkWidget *new_font_menuitem;
1923 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1924 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1926 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1927 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1928 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1929 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1931 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1932 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1933 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1936 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1938 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1939 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1941 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1942 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1944 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1945 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1948 switch (buffer_format->justification)
1950 case GTK_JUSTIFY_LEFT:
1951 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1953 case GTK_JUSTIFY_CENTER:
1954 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1956 case GTK_JUSTIFY_RIGHT:
1957 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1964 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1966 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1967 G_CALLBACK (modest_msg_edit_window_color_button_change),
1969 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1970 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1971 G_CALLBACK (modest_msg_edit_window_color_button_change),
1974 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1975 buffer_format->font_size))->data);
1976 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1980 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1981 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1982 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1984 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1985 G_CALLBACK (modest_msg_edit_window_size_change),
1987 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1988 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1989 G_CALLBACK (modest_msg_edit_window_size_change),
1993 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1994 buffer_format->font))->data);
1995 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1999 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2000 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2001 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2003 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2004 G_CALLBACK (modest_msg_edit_window_font_change),
2006 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2007 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2008 G_CALLBACK (modest_msg_edit_window_font_change),
2012 g_free (buffer_format);
2018 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2021 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2022 ModestMsgEditWindowPrivate *priv;
2023 GtkWidget *dialog = NULL;
2025 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2026 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2028 dialog = hildon_color_chooser_new ();
2029 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2030 g_free (buffer_format);
2032 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2034 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2035 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2038 gtk_widget_destroy (dialog);
2043 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2046 ModestMsgEditWindowPrivate *priv;
2047 GtkWidget *dialog = NULL;
2048 GdkColor *old_color = NULL;
2050 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2051 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2053 dialog = hildon_color_chooser_new ();
2054 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2056 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2058 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2059 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2061 gtk_widget_destroy (dialog);
2066 create_stream_for_uri (const gchar* uri)
2071 TnyStream *result = NULL;
2073 GnomeVFSHandle *handle = NULL;
2074 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2075 if (test == GNOME_VFS_OK) {
2076 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2077 /* Streams over OBEX (Bluetooth) are not seekable but
2078 * we expect them to be (we might need to read them
2079 * several times). So if this is a Bluetooth URI just
2080 * read the whole file into memory (this is not a fast
2081 * protocol so we can assume that these files are not
2082 * going to be very big) */
2083 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2084 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2085 TnyStream *memstream = tny_camel_mem_stream_new ();
2086 tny_stream_write_to_stream (vfssstream, memstream);
2087 g_object_unref (vfssstream);
2090 result = vfssstream;
2098 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2101 ModestMsgEditWindowPrivate *priv;
2102 GtkWidget *dialog = NULL;
2104 GSList *uris = NULL;
2105 GSList *uri_node = NULL;
2107 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2109 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2110 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2111 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2113 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2115 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2116 GTK_WINDOW (dialog),
2117 GTK_WINDOW (window));
2119 response = gtk_dialog_run (GTK_DIALOG (dialog));
2121 case GTK_RESPONSE_OK:
2122 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2127 gtk_widget_destroy (dialog);
2129 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2131 GnomeVFSHandle *handle = NULL;
2132 GnomeVFSResult result;
2133 GtkTextIter position;
2134 GtkTextMark *insert_mark;
2136 uri = (const gchar *) uri_node->data;
2137 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2138 if (result == GNOME_VFS_OK) {
2140 GnomeVFSFileInfo *info;
2141 gchar *filename, *basename, *escaped_filename;
2142 TnyMimePart *mime_part;
2144 const gchar *mime_type = NULL;
2145 GnomeVFSURI *vfs_uri;
2146 guint64 stream_size;
2148 gnome_vfs_close (handle);
2149 vfs_uri = gnome_vfs_uri_new (uri);
2151 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2152 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2153 g_free (escaped_filename);
2154 gnome_vfs_uri_unref (vfs_uri);
2155 info = gnome_vfs_file_info_new ();
2157 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2158 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2160 mime_type = gnome_vfs_file_info_get_mime_type (info);
2162 mime_part = tny_platform_factory_new_mime_part
2163 (modest_runtime_get_platform_factory ());
2165 TnyStream *stream = create_stream_for_uri (uri);
2167 if (stream == NULL) {
2169 modest_platform_information_banner (NULL, NULL,
2170 _FM("sfil_ib_opening_not_allowed"));
2172 g_object_unref (mime_part);
2173 gnome_vfs_file_info_unref (info);
2177 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2179 content_id = g_strdup_printf ("%d", priv->next_cid);
2180 tny_mime_part_set_content_id (mime_part, content_id);
2181 g_free (content_id);
2184 basename = g_path_get_basename (filename);
2185 tny_mime_part_set_filename (mime_part, basename);
2188 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2190 if (pixbuf != NULL) {
2191 priv->images_size += stream_size;
2192 priv->images_count ++;
2193 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2194 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2195 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2198 tny_list_prepend (priv->images, (GObject *) mime_part);
2199 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2201 g_object_unref (mime_part);
2202 gnome_vfs_file_info_unref (info);
2211 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2213 GtkWidget *dialog = NULL;
2215 GSList *uris = NULL;
2217 GnomeVFSFileSize total_size, allowed_size;
2218 ModestMsgEditWindowPrivate *priv;
2222 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2224 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2226 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2229 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2230 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2231 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2232 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), GTK_WINDOW (window));
2234 response = gtk_dialog_run (GTK_DIALOG (dialog));
2236 case GTK_RESPONSE_OK:
2237 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2242 gtk_widget_destroy (dialog);
2244 /* allowed size is the maximum size - what's already there */
2245 modest_attachments_view_get_sizes (
2246 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2247 &att_num, &att_size);
2248 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2251 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2253 const gchar *uri = (const gchar *) uri_node->data;
2255 total_size += modest_msg_edit_window_attach_file_one
2256 (window, uri, allowed_size);
2258 if (total_size > allowed_size) {
2259 g_warning ("%s: total size: %u",
2260 __FUNCTION__, (unsigned int)total_size);
2264 allowed_size -= total_size;
2268 g_slist_foreach (uris, (GFunc) g_free, NULL);
2269 g_slist_free (uris);
2274 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2276 GnomeVFSFileSize allowed_size)
2279 GnomeVFSHandle *handle = NULL;
2280 ModestMsgEditWindowPrivate *priv;
2281 GnomeVFSResult result;
2282 GnomeVFSFileSize size = 0;
2283 g_return_val_if_fail (window, 0);
2284 g_return_val_if_fail (uri, 0);
2286 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2288 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2289 if (result == GNOME_VFS_OK) {
2290 TnyMimePart *mime_part;
2292 const gchar *mime_type = NULL;
2294 gchar *escaped_filename;
2297 GnomeVFSFileInfo *info;
2298 GnomeVFSURI *vfs_uri;
2300 gnome_vfs_close (handle);
2301 vfs_uri = gnome_vfs_uri_new (uri);
2304 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2305 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2306 g_free (escaped_filename);
2307 gnome_vfs_uri_unref (vfs_uri);
2309 info = gnome_vfs_file_info_new ();
2311 if (gnome_vfs_get_file_info (uri,
2313 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2315 mime_type = gnome_vfs_file_info_get_mime_type (info);
2316 mime_part = tny_platform_factory_new_mime_part
2317 (modest_runtime_get_platform_factory ());
2319 /* try to get the attachment's size; this may fail for weird
2320 * file systems, like obex, upnp... */
2321 if (allowed_size != 0 &&
2322 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2324 if (size > allowed_size) {
2325 modest_platform_information_banner (NULL, NULL,
2326 _("mail_ib_error_attachment_size"));
2330 g_debug ("%s: could not get attachment size", __FUNCTION__);
2332 stream = create_stream_for_uri (uri);
2334 if (stream == NULL) {
2336 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2338 g_object_unref (mime_part);
2339 gnome_vfs_file_info_unref (info);
2343 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2344 g_object_unref (stream);
2346 content_id = g_strdup_printf ("%d", priv->next_cid);
2347 tny_mime_part_set_content_id (mime_part, content_id);
2348 g_free (content_id);
2351 basename = g_path_get_basename (filename);
2352 tny_mime_part_set_filename (mime_part, basename);
2355 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2356 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2358 info->size == 0, info->size);
2359 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2360 gtk_widget_show_all (priv->attachments_caption);
2361 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2363 g_object_unref (mime_part);
2364 gnome_vfs_file_info_unref (info);
2371 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2374 ModestMsgEditWindowPrivate *priv;
2377 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2378 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2380 if (att_list == NULL) {
2381 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2383 g_object_ref (att_list);
2386 if (tny_list_get_length (att_list) == 0) {
2387 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2389 gboolean dialog_response;
2390 gchar *message = NULL;
2391 gchar *filename = NULL;
2393 if (tny_list_get_length (att_list) == 1) {
2395 iter = tny_list_create_iterator (att_list);
2396 part = (TnyMimePart *) tny_iterator_get_current (iter);
2397 g_object_unref (iter);
2398 if (TNY_IS_MSG (part)) {
2399 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2401 filename = tny_header_dup_subject (header);
2402 g_object_unref (header);
2404 if (filename == NULL) {
2405 filename = g_strdup (_("mail_va_no_subject"));
2408 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2410 g_object_unref (part);
2412 filename = g_strdup ("");
2414 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2415 tny_list_get_length (att_list)), filename);
2418 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2421 if (dialog_response != GTK_RESPONSE_OK) {
2422 g_object_unref (att_list);
2425 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
2427 for (iter = tny_list_create_iterator (att_list);
2428 !tny_iterator_is_done (iter);
2429 tny_iterator_next (iter)) {
2430 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2431 const gchar *att_id;
2432 tny_list_remove (priv->attachments, (GObject *) mime_part);
2434 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2436 if (tny_list_get_length (priv->attachments) == 0)
2437 gtk_widget_hide (priv->attachments_caption);
2438 att_id = tny_mime_part_get_content_id (mime_part);
2440 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2442 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2443 g_object_unref (mime_part);
2445 g_object_unref (iter);
2448 g_object_unref (att_list);
2450 /* if the last attachment has been removed, focus the Subject: field */
2451 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2452 gtk_widget_grab_focus (priv->subject_field);
2456 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2459 ModestMsgEditWindowPrivate *priv;
2460 GdkColor *new_color;
2461 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2463 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), new_color);
2465 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2467 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2472 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2475 ModestMsgEditWindowPrivate *priv;
2476 gint new_size_index;
2477 ModestMsgEditWindow *window;
2480 window = MODEST_MSG_EDIT_WINDOW (userdata);
2481 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2482 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2484 if (gtk_check_menu_item_get_active (menu_item)) {
2486 WPTextBufferFormat format;
2488 memset (&format, 0, sizeof (format));
2489 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2491 label = gtk_bin_get_child (GTK_BIN (menu_item));
2493 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2494 format.cs.font_size = TRUE;
2495 format.cs.text_position = TRUE;
2496 format.cs.font = TRUE;
2497 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2498 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2500 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2501 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2502 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2504 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2505 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2506 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2512 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2515 ModestMsgEditWindowPrivate *priv;
2516 gint new_font_index;
2517 ModestMsgEditWindow *window;
2520 window = MODEST_MSG_EDIT_WINDOW (userdata);
2521 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2522 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2524 if (gtk_check_menu_item_get_active (menu_item)) {
2527 label = gtk_bin_get_child (GTK_BIN (menu_item));
2529 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2531 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2532 GINT_TO_POINTER(new_font_index)))
2533 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2535 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2536 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2537 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2543 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2545 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2546 ModestWindowPrivate *parent_priv;
2547 ModestWindowMgr *mgr;
2548 gboolean is_fullscreen;
2549 GtkAction *fs_toggle_action;
2552 mgr = modest_runtime_get_window_mgr ();
2553 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2555 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2557 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2558 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2559 if (is_fullscreen != active)
2560 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2568 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2571 ModestMsgEditWindowPrivate *priv = NULL;
2572 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2574 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2575 if (!priv->update_caption_visibility)
2578 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2580 gtk_widget_show (priv->cc_caption);
2582 gtk_widget_hide (priv->cc_caption);
2584 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2588 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2591 ModestMsgEditWindowPrivate *priv = NULL;
2592 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2594 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2595 if (!priv->update_caption_visibility)
2598 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2600 gtk_widget_show (priv->bcc_caption);
2602 gtk_widget_hide (priv->bcc_caption);
2604 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2608 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2609 ModestRecptEditor *editor)
2611 ModestMsgEditWindowPrivate *priv;
2613 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2614 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2616 /* we check for low-mem; in that case, show a warning, and don't allow
2617 * for the addressbook
2619 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2622 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2624 if (editor == NULL) {
2625 GtkWidget *view_focus;
2626 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2628 /* This code should be kept in sync with ModestRecptEditor. The
2629 textview inside the recpt editor is the one that really gets the
2630 focus. As it's inside a scrolled window, and this one inside the
2631 hbox recpt editor inherits from, we'll need to go up in the
2632 hierarchy to know if the text view is part of the recpt editor
2633 or if it's a different text entry */
2635 if (gtk_widget_get_parent (view_focus)) {
2636 GtkWidget *first_parent;
2638 first_parent = gtk_widget_get_parent (view_focus);
2639 if (gtk_widget_get_parent (first_parent) &&
2640 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2641 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2646 editor = MODEST_RECPT_EDITOR (priv->to_field);
2650 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
2655 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2657 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2659 modest_msg_edit_window_open_addressbook (window, NULL);
2663 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2664 gboolean show_toolbar)
2666 ModestWindowPrivate *parent_priv;
2667 const gchar *action_name;
2670 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2671 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2673 /* We can not just use the code of
2674 modest_msg_edit_window_setup_toolbar because it has a
2675 mixture of both initialization and creation code. */
2677 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2679 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2681 /* Update also the actions (to update the toggles in the
2682 menus), we have to do it manually because some other window
2683 of the same time could have changed it (remember that the
2684 toolbar fullscreen mode is shared by all the windows of the
2686 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2687 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2689 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2691 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2692 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
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), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2717 gtk_widget_show (priv->priority_icon);
2718 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2719 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2721 case TNY_HEADER_FLAG_LOW_PRIORITY:
2722 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2723 gtk_widget_show (priv->priority_icon);
2724 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2725 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2728 gtk_widget_hide (priv->priority_icon);
2729 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2730 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2733 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2734 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2739 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2742 ModestMsgEditWindowPrivate *priv;
2743 ModestWindowPrivate *parent_priv;
2744 gint current_format;
2746 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2748 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2749 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2751 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2752 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2754 if (current_format != file_format) {
2755 switch (file_format) {
2756 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2757 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2758 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2760 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2764 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2765 response = gtk_dialog_run (GTK_DIALOG (dialog));
2766 gtk_widget_destroy (dialog);
2767 if (response == GTK_RESPONSE_OK) {
2768 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2770 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2771 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2776 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2777 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2778 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2783 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2786 ModestMsgEditWindowPrivate *priv;
2787 WPTextBufferFormat oldfmt, fmt;
2788 gint old_position = 0;
2792 GdkColor *color = NULL;
2793 gboolean bold, bold_set, italic, italic_set;
2794 gboolean underline, underline_set;
2795 gboolean strikethrough, strikethrough_set;
2796 gboolean position_set;
2797 gboolean font_size_set, font_set, color_set;
2800 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2801 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2803 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2804 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2805 GTK_WINDOW(dialog), GTK_WINDOW (window));
2807 /* First we get the currently selected font information */
2808 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2810 switch (oldfmt.text_position) {
2811 case TEXT_POSITION_NORMAL:
2814 case TEXT_POSITION_SUPERSCRIPT:
2822 g_object_set (G_OBJECT (dialog),
2823 "bold", oldfmt.bold != FALSE,
2824 "bold-set", !oldfmt.cs.bold,
2825 "underline", oldfmt.underline != FALSE,
2826 "underline-set", !oldfmt.cs.underline,
2827 "italic", oldfmt.italic != FALSE,
2828 "italic-set", !oldfmt.cs.italic,
2829 "strikethrough", oldfmt.strikethrough != FALSE,
2830 "strikethrough-set", !oldfmt.cs.strikethrough,
2831 "color", &oldfmt.color,
2832 "color-set", !oldfmt.cs.color,
2833 "size", wp_font_size[oldfmt.font_size],
2834 "size-set", !oldfmt.cs.font_size,
2835 "position", old_position,
2836 "position-set", !oldfmt.cs.text_position,
2837 "family", wp_get_font_name (oldfmt.font),
2838 "family-set", !oldfmt.cs.font,
2841 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2842 GTK_WINDOW (dialog), GTK_WINDOW (window));
2843 gtk_widget_show_all (dialog);
2844 priv->font_dialog = dialog;
2845 response = gtk_dialog_run (GTK_DIALOG (dialog));
2846 priv->font_dialog = NULL;
2847 if (response == GTK_RESPONSE_OK) {
2849 g_object_get( dialog,
2851 "bold-set", &bold_set,
2852 "underline", &underline,
2853 "underline-set", &underline_set,
2855 "italic-set", &italic_set,
2856 "strikethrough", &strikethrough,
2857 "strikethrough-set", &strikethrough_set,
2859 "color-set", &color_set,
2861 "size-set", &font_size_set,
2862 "family", &font_name,
2863 "family-set", &font_set,
2864 "position", &position,
2865 "position-set", &position_set,
2870 if (response == GTK_RESPONSE_OK) {
2871 memset(&fmt, 0, sizeof(fmt));
2877 fmt.italic = italic;
2878 fmt.cs.italic = TRUE;
2880 if (underline_set) {
2881 fmt.underline = underline;
2882 fmt.cs.underline = TRUE;
2884 if (strikethrough_set) {
2885 fmt.strikethrough = strikethrough;
2886 fmt.cs.strikethrough = TRUE;
2891 ? TEXT_POSITION_NORMAL
2892 : ( ( position == 1 )
2893 ? TEXT_POSITION_SUPERSCRIPT
2894 : TEXT_POSITION_SUBSCRIPT );
2895 fmt.cs.text_position = TRUE;
2896 fmt.font_size = oldfmt.font_size;
2900 fmt.cs.color = TRUE;
2903 fmt.font = wp_get_font_index(font_name,
2908 if (font_size_set) {
2909 fmt.cs.font_size = TRUE;
2910 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2912 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2913 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2915 gtk_widget_destroy (dialog);
2917 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2921 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2923 ModestMsgEditWindowPrivate *priv;
2925 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2926 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2928 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2930 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2931 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2935 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2937 ModestMsgEditWindowPrivate *priv;
2939 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2940 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2942 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2944 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2945 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2950 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2952 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2954 priv->can_undo = can_undo;
2958 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2960 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2962 priv->can_redo = can_redo;
2966 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2968 ModestMsgEditWindowPrivate *priv;
2969 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2970 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2972 return priv->can_undo;
2976 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2978 ModestMsgEditWindowPrivate *priv;
2979 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2980 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2982 return priv->can_redo;
2987 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2990 GtkTextIter match_start, match_end;
2992 if (image_id == NULL)
2995 gtk_text_buffer_get_start_iter (buffer, &iter);
2997 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2998 GSList *tags = gtk_text_iter_get_tags (&match_start);
3000 for (node = tags; node != NULL; node = g_slist_next (node)) {
3001 GtkTextTag *tag = (GtkTextTag *) node->data;
3002 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3003 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3004 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3006 offset = gtk_text_iter_get_offset (&match_start);
3007 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3008 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3012 gtk_text_iter_forward_char (&iter);
3017 message_is_empty (ModestMsgEditWindow *window)
3019 ModestMsgEditWindowPrivate *priv = NULL;
3021 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3022 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3024 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3025 * so we can ignore markup.
3027 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3030 count = gtk_text_buffer_get_char_count (buf);
3036 msg_body_focus (GtkWidget *focus,
3037 GdkEventFocus *event,
3041 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3042 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3043 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3048 recpt_field_changed (GtkTextBuffer *buffer,
3049 ModestMsgEditWindow *editor)
3051 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3052 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3056 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3058 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3059 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3063 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3066 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3067 GtkTextBuffer *buffer;
3069 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3070 gtk_text_buffer_set_modified (buffer, modified);
3071 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3072 gtk_text_buffer_set_modified (buffer, modified);
3073 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3074 gtk_text_buffer_set_modified (buffer, modified);
3075 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3079 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3081 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3082 const char *account_name;
3083 GtkTextBuffer *buffer;
3085 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3086 if (gtk_text_buffer_get_modified (buffer))
3088 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3089 if (gtk_text_buffer_get_modified (buffer))
3091 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3092 if (gtk_text_buffer_get_modified (buffer))
3094 if (gtk_text_buffer_get_modified (priv->text_buffer))
3096 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
3097 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3108 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3110 ModestMsgEditWindowPrivate *priv = NULL;
3111 GSList *address_list = NULL;
3113 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3114 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3116 /* check if there's no recipient added */
3117 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3118 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3119 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3120 /* no recipient contents, then select contacts */
3121 modest_msg_edit_window_open_addressbook (window, NULL);
3126 g_object_ref (window);
3127 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), &address_list)) {
3128 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3129 g_object_unref (window);
3132 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), &address_list)) {
3133 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3134 g_object_unref (window);
3137 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), &address_list)) {
3138 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3139 g_object_unref (window);
3143 /* Add contacts to address book */
3145 modest_address_book_add_address_list (address_list);
3147 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3148 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3149 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3150 g_object_unref (window);
3157 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3158 ModestMsgEditWindow *window)
3160 modest_msg_edit_window_offer_attach_file (window);
3164 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3166 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3168 return priv->clipboard_text;
3172 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3174 ModestMsgEditWindow *window)
3176 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3177 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3179 if (!GTK_WIDGET_VISIBLE (window))
3182 g_object_ref (window);
3183 text = gtk_clipboard_wait_for_text (selection_clipboard);
3185 if (priv->clipboard_text != NULL) {
3186 g_free (priv->clipboard_text);
3188 priv->clipboard_text = text;
3190 if (GTK_WIDGET_VISIBLE (window)) {
3191 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3193 g_object_unref (window);
3196 static gboolean clipboard_owner_change_idle (gpointer userdata)
3198 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3199 ModestMsgEditWindowPrivate *priv;
3201 gdk_threads_enter ();
3202 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3203 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3205 priv->clipboard_owner_idle = 0;
3206 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3207 gdk_threads_leave ();
3213 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3215 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3216 if (priv->clipboard_owner_idle == 0) {
3217 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3222 subject_field_move_cursor (GtkEntry *entry,
3223 GtkMovementStep step,
3228 if (!GTK_WIDGET_VISIBLE (window))
3231 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3235 update_window_title (ModestMsgEditWindow *window)
3237 ModestMsgEditWindowPrivate *priv = NULL;
3238 const gchar *subject;
3240 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3241 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3242 if (subject == NULL || subject[0] == '\0')
3243 subject = _("mail_va_new_email");
3245 gtk_window_set_title (GTK_WINDOW (window), subject);
3250 subject_field_changed (GtkEditable *editable,
3251 ModestMsgEditWindow *window)
3253 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3254 update_window_title (window);
3255 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3256 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3257 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3261 subject_field_insert_text (GtkEditable *editable,
3263 gint new_text_length,
3265 ModestMsgEditWindow *window)
3267 GString *result = g_string_new ("");
3269 gint result_len = 0;
3270 const gchar *entry_text = NULL;
3273 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3274 old_length = g_utf8_strlen (entry_text, -1);
3276 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3277 gunichar c = g_utf8_get_char_validated (current, 8);
3278 /* Invalid unichar, stop */
3284 result = g_string_append_unichar (result, c);
3288 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3289 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3292 /* Prevent endless recursion */
3293 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3294 g_signal_emit_by_name (editable, "insert-text",
3295 (gpointer) result->str, (gpointer) result->len,
3296 (gpointer) position, (gpointer) window);
3297 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3301 if (result_len + old_length > 1000) {
3302 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3303 _CS("ckdg_ib_maximum_characters_reached"));
3306 g_string_free (result, TRUE);
3310 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3313 ModestMsgEditWindowPrivate *priv = NULL;
3315 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3316 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3318 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3321 gtk_widget_show_all (priv->find_toolbar);
3322 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3324 gtk_widget_hide_all (priv->find_toolbar);
3325 gtk_widget_grab_focus (priv->msg_body);
3331 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3333 GtkTextIter *match_start,
3334 GtkTextIter *match_end)
3336 GtkTextIter end_iter;
3337 gchar *str_casefold;
3340 gchar *range_casefold;
3343 gboolean result = FALSE;
3350 gtk_text_iter_forward_to_end (&end_iter);
3352 str_casefold = g_utf8_casefold (str, -1);
3353 str_chars_n = strlen (str);
3355 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3356 range_casefold = g_utf8_casefold (range_text, -1);
3357 range_chars_n = strlen (range_casefold);
3359 if (range_chars_n < str_chars_n) {
3360 g_free (str_casefold);
3361 g_free (range_text);
3362 g_free (range_casefold);
3366 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3367 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3368 if (!g_utf8_collate (range_subtext, str_casefold)) {
3369 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3371 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3372 match_start, match_end, NULL);
3373 g_free (found_text);
3375 g_free (range_subtext);
3379 g_free (str_casefold);
3380 g_free (range_text);
3381 g_free (range_casefold);
3388 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3389 ModestMsgEditWindow *window)
3391 gchar *current_search = NULL;
3392 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3394 GtkTextIter selection_start, selection_end;
3395 GtkTextIter match_start, match_end;
3396 gboolean continue_search = FALSE;
3398 if (message_is_empty (window)) {
3399 g_free (priv->last_search);
3400 priv->last_search = NULL;
3401 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3405 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3406 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3407 g_free (current_search);
3408 g_free (priv->last_search);
3409 priv->last_search = NULL;
3410 /* Information banner about empty search */
3411 hildon_banner_show_information (NULL, NULL,
3412 _CS ("ecdg_ib_find_rep_enter_text"));
3416 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3417 continue_search = TRUE;
3419 g_free (priv->last_search);
3420 priv->last_search = g_strdup (current_search);
3423 if (continue_search) {
3424 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3425 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3426 &match_start, &match_end);
3428 hildon_banner_show_information (NULL, NULL,
3429 _HL ("ckct_ib_find_search_complete"));
3431 GtkTextIter buffer_start;
3432 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3433 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3434 &match_start, &match_end);
3436 hildon_banner_show_information (NULL, NULL,
3437 _HL ("ckct_ib_find_no_matches"));
3440 /* Mark as selected the string found in search */
3442 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3443 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3444 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3446 g_free (priv->last_search);
3447 priv->last_search = NULL;
3449 g_free (current_search);
3453 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3454 ModestMsgEditWindow *window)
3456 GtkToggleAction *toggle;
3457 ModestWindowPrivate *parent_priv;
3458 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3460 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3461 gtk_toggle_action_set_active (toggle, FALSE);
3465 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3467 ModestMsgEditWindowPrivate *priv;
3469 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3474 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3477 ModestMsgEditWindowPrivate *priv;
3479 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3485 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3488 ModestMsgEditWindowPrivate *priv;
3489 TnyHeader *header = NULL;
3491 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3492 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3494 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3495 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3497 if (priv->draft_msg != NULL) {
3498 g_object_unref (priv->draft_msg);
3501 if (draft != NULL) {
3502 g_object_ref (draft);
3503 header = tny_msg_get_header (draft);
3504 if (priv->msg_uid) {
3505 g_free (priv->msg_uid);
3506 priv->msg_uid = NULL;
3508 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3509 if (GTK_WIDGET_REALIZED (window))
3510 modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL);
3513 priv->draft_msg = draft;
3517 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3518 GtkTextIter *start, GtkTextIter *end,
3521 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3522 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3525 if (tag == NULL) return;
3526 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3527 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3528 replace_with_images (window, priv->images);
3533 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3536 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3538 g_return_if_fail (TNY_IS_MIME_PART (part));
3539 tny_list_prepend (priv->attachments, (GObject *) part);
3540 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3541 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3542 gtk_widget_show_all (priv->attachments_caption);
3543 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3547 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3549 ModestMsgEditWindowPrivate *priv;
3551 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3552 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3554 return priv->msg_uid;
3558 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3559 ModestMsgEditWindowWidgetType widget_type)
3561 ModestMsgEditWindowPrivate *priv;
3563 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3564 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3566 switch (widget_type) {
3567 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3568 return priv->msg_body;
3570 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3571 return priv->to_field;
3573 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3574 return priv->cc_field;
3576 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3577 return priv->bcc_field;
3579 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3580 return priv->subject_field;
3582 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3583 return priv->attachments_view;
3591 remove_tags (WPTextBuffer *buffer)
3593 GtkTextIter start, end;
3595 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3596 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3598 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3602 on_account_removed (TnyAccountStore *account_store,
3603 TnyAccount *account,
3606 /* Do nothing if it's a store account, because we use the
3607 transport to send the messages */
3608 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3609 const gchar *parent_acc = NULL;
3610 const gchar *our_acc = NULL;
3612 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3613 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3614 /* Close this window if I'm showing a message of the removed account */
3615 if (strcmp (parent_acc, our_acc) == 0)
3616 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3621 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3623 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3625 hildon_banner_show_information (NULL, NULL,
3626 _CS("ckct_ib_cannot_zoom_here"));
3632 set_zoom_do_nothing (ModestWindow *window,
3638 get_zoom_do_nothing (ModestWindow *window)