1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
42 #include <modest-account-mgr.h>
43 #include <modest-account-mgr-helpers.h>
45 #include <widgets/modest-msg-edit-window.h>
46 #include <widgets/modest-combo-box.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <wptextview.h>
65 #include <wptextbuffer.h>
66 #include "modest-scroll-area.h"
67 #include "modest-msg-edit-window-ui-dimming.h"
69 #include "modest-hildon-includes.h"
70 #ifdef MODEST_HAVE_HILDON0_WIDGETS
71 #include <hildon-widgets/hildon-color-chooser.h>
73 #include "widgets/modest-msg-edit-window-ui.h"
74 #ifdef MODEST_HAVE_HILDON0_WIDGETS
75 #include <libgnomevfs/gnome-vfs-mime-utils.h>
77 #include <libgnomevfs/gnome-vfs-mime.h>
79 #include <modest-utils.h>
80 #include "modest-maemo-utils.h"
83 #define DEFAULT_FONT_SIZE 3
84 #define DEFAULT_FONT 2
85 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
86 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
87 #define DEFAULT_MAIN_VBOX_SPACING 6
88 #define SUBJECT_MAX_LENGTH 1000
89 #define IMAGE_MAX_WIDTH 560
90 #define DEFAULT_FONT_SCALE 1.5
92 static gboolean is_wp_text_buffer_started = FALSE;
94 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
95 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
96 static void modest_msg_edit_window_finalize (GObject *obj);
98 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
99 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
100 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
102 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
103 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
104 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
105 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
106 GtkTextIter *start, GtkTextIter *end,
108 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
109 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
110 static void subject_field_insert_text (GtkEditable *editable,
112 gint new_text_length,
114 ModestMsgEditWindow *window);
115 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
117 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
119 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
121 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
122 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
123 GdkEventWindowState *event,
125 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
126 ModestRecptEditor *editor);
127 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
128 ModestMsgEditWindow *window);
130 /* ModestWindow methods implementation */
131 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
132 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
133 gboolean show_toolbar);
134 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
136 ModestMsgEditWindow *window);
137 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
138 static void subject_field_move_cursor (GtkEntry *entry,
139 GtkMovementStep step,
143 static void update_window_title (ModestMsgEditWindow *window);
146 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
147 ModestMsgEditWindow *window);
148 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
149 ModestMsgEditWindow *window);
150 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
152 GtkTextIter *match_start,
153 GtkTextIter *match_end);
155 static void remove_tags (WPTextBuffer *buffer);
157 static void on_account_removed (TnyAccountStore *account_store,
161 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
162 static void set_zoom_do_nothing (ModestWindow *window, gdouble zoom);
163 static gdouble get_zoom_do_nothing (ModestWindow *window);
165 static void init_window (ModestMsgEditWindow *obj);
167 gboolean scroll_drag_timeout (gpointer userdata);
168 static void correct_scroll (ModestMsgEditWindow *w);
169 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
170 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
171 ModestMsgEditWindow *userdata);
172 static void text_buffer_mark_set (GtkTextBuffer *buffer,
175 ModestMsgEditWindow *userdata);
176 static void vadj_changed (GtkAdjustment *adj,
177 ModestMsgEditWindow *window);
179 static void DEBUG_BUFFER (WPTextBuffer *buffer)
183 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
185 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
186 while (!gtk_text_iter_is_end (&iter)) {
187 GString *output = g_string_new ("");
188 GSList *toggled_tags;
191 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
192 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
193 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
194 GtkTextTag *tag = (GtkTextTag *) node->data;
196 g_object_get (G_OBJECT (tag), "name", &name, NULL);
197 output = g_string_append (output, name);
198 g_string_append (output, " ");
200 output = g_string_append (output, "] OPENED [ ");
201 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
202 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
203 GtkTextTag *tag = (GtkTextTag *) node->data;
205 g_object_get (G_OBJECT (tag), "name", &name, NULL);
206 output = g_string_append (output, name);
207 g_string_append (output, " ");
209 output = g_string_append (output, "]\n");
210 g_message ("%s", output->str);
211 g_string_free (output, TRUE);
212 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
214 g_message ("END BUFFER");
219 /* static gboolean */
220 /* on_key_pressed (GtkWidget *self, */
221 /* GdkEventKey *event, */
222 /* gpointer user_data); */
224 /* list my signals */
231 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
232 struct _ModestMsgEditWindowPrivate {
235 GtkWidget *header_box;
237 ModestPairList *from_field_protos;
238 GtkWidget *from_field;
239 gchar *original_account_name;
243 GtkWidget *bcc_field;
244 GtkWidget *subject_field;
245 GtkWidget *attachments_view;
246 GtkWidget *priority_icon;
247 GtkWidget *add_attachment_button;
249 GtkWidget *cc_caption;
250 GtkWidget *bcc_caption;
251 gboolean update_caption_visibility;
252 GtkWidget *attachments_caption;
254 GtkTextBuffer *text_buffer;
256 GtkWidget *font_size_toolitem;
257 GtkWidget *font_face_toolitem;
258 GtkWidget *font_color_button;
259 GSList *font_items_group;
260 GtkWidget *font_tool_button_label;
261 GSList *size_items_group;
262 GtkWidget *size_tool_button_label;
264 GtkWidget *find_toolbar;
267 GtkWidget *font_dialog;
270 guint scroll_drag_timeout_id;
274 TnyList *attachments;
279 TnyHeaderFlags priority_flags;
281 gboolean can_undo, can_redo;
282 gulong clipboard_change_handler_id;
283 gulong default_clipboard_change_handler_id;
284 gulong account_removed_handler_id;
285 guint clipboard_owner_idle;
286 gchar *clipboard_text;
295 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
296 MODEST_TYPE_MSG_EDIT_WINDOW, \
297 ModestMsgEditWindowPrivate))
299 static GtkWindowClass *parent_class = NULL;
301 /* uncomment the following if you have defined any signals */
302 /* static guint signals[LAST_SIGNAL] = {0}; */
305 modest_msg_edit_window_get_type (void)
307 static GType my_type = 0;
309 static const GTypeInfo my_info = {
310 sizeof(ModestMsgEditWindowClass),
311 NULL, /* base init */
312 NULL, /* base finalize */
313 (GClassInitFunc) modest_msg_edit_window_class_init,
314 NULL, /* class finalize */
315 NULL, /* class data */
316 sizeof(ModestMsgEditWindow),
318 (GInstanceInitFunc) modest_msg_edit_window_init,
321 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
322 "ModestMsgEditWindow",
330 save_state (ModestWindow *self)
332 modest_widget_memory_save (modest_runtime_get_conf(),
333 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
338 restore_settings (ModestMsgEditWindow *self)
340 ModestConf *conf = NULL;
342 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
344 conf = modest_runtime_get_conf ();
345 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
346 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
347 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
348 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL));
349 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
350 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu");
351 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
352 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
354 /* set initial state of cc and bcc */
355 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
356 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
357 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
358 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
359 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
360 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
362 /* Dim at start clipboard actions */
363 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
364 gtk_action_set_sensitive (action, FALSE);
365 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
366 gtk_action_set_sensitive (action, FALSE);
367 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
368 gtk_action_set_sensitive (action, FALSE);
370 modest_widget_memory_restore (conf,
371 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
376 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
378 GObjectClass *gobject_class;
379 ModestWindowClass *modest_window_class;
380 gobject_class = (GObjectClass*) klass;
381 modest_window_class = (ModestWindowClass*) klass;
383 parent_class = g_type_class_peek_parent (klass);
384 gobject_class->finalize = modest_msg_edit_window_finalize;
386 modest_window_class->set_zoom_func = set_zoom_do_nothing;
387 modest_window_class->get_zoom_func = get_zoom_do_nothing;
388 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
389 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
390 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
391 modest_window_class->save_state_func = save_state;
392 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
394 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
398 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
400 ModestMsgEditWindowPrivate *priv;
401 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
403 priv->msg_body = NULL;
405 priv->from_field = NULL;
406 priv->to_field = NULL;
407 priv->cc_field = NULL;
408 priv->bcc_field = NULL;
409 priv->subject_field = NULL;
410 priv->attachments = TNY_LIST (tny_simple_list_new ());
411 priv->images = TNY_LIST (tny_simple_list_new ());
412 priv->images_size = 0;
413 priv->images_count = 0;
416 priv->cc_caption = NULL;
417 priv->bcc_caption = NULL;
418 priv->update_caption_visibility = FALSE;
420 priv->priority_flags = 0;
422 priv->find_toolbar = NULL;
423 priv->last_search = NULL;
425 priv->draft_msg = NULL;
426 priv->outbox_msg = NULL;
427 priv->msg_uid = NULL;
429 priv->can_undo = FALSE;
430 priv->can_redo = FALSE;
431 priv->clipboard_change_handler_id = 0;
432 priv->default_clipboard_change_handler_id = 0;
433 priv->account_removed_handler_id = 0;
434 priv->clipboard_owner_idle = 0;
435 priv->clipboard_text = NULL;
438 priv->scroll_drag_timeout_id = 0;
439 priv->last_upper = 0.0;
441 priv->font_dialog = NULL;
443 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
444 GTK_WINDOW(obj),"applications_email_editor");
446 if (!is_wp_text_buffer_started) {
447 is_wp_text_buffer_started = TRUE;
448 wp_text_buffer_library_init ();
453 hildon_program_add_window (hildon_program_get_instance(),
458 /* FIXME: this is a dup from the one in gtk/ */
461 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
463 static ModestPairList*
464 get_transports (void)
466 GSList *transports = NULL;
468 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
469 GSList *accounts = modest_account_mgr_account_names (account_mgr,
470 TRUE /* only enabled accounts. */);
472 GSList *cursor = accounts;
474 gchar *account_name = cursor->data;
475 gchar *from_string = NULL;
477 from_string = modest_account_mgr_get_from_string (account_mgr,
481 if (from_string && account_name) {
482 gchar *name = account_name;
483 ModestPair *pair = modest_pair_new ((gpointer) name,
484 (gpointer) from_string , TRUE);
485 transports = g_slist_prepend (transports, pair);
488 cursor = cursor->next;
490 g_slist_free (accounts); /* only free the accounts, not the elements,
491 * because they are used in the pairlist */
495 static void window_focus (GtkWindow *window,
499 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
503 scroll_drag_timeout (gpointer userdata)
505 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
506 ModestMsgEditWindowPrivate *priv;
508 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
510 correct_scroll_without_drag_check (win, TRUE);
512 priv->scroll_drag_timeout_id = 0;
518 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
520 ModestMsgEditWindowPrivate *priv;
523 GdkRectangle rectangle;
529 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
531 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
534 insert = gtk_text_buffer_get_insert (priv->text_buffer);
535 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
537 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
538 vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll));
539 offset = priv->msg_body->allocation.y;
541 new_value = vadj->value;
543 if ((offset + rectangle.y + rectangle.height) >
544 ((gint) (vadj->value +vadj->page_size))) {
545 new_value = (offset + rectangle.y) - vadj->page_size * 0.25;
546 if (new_value > vadj->upper - vadj->page_size)
547 new_value = vadj->upper - vadj->page_size;
548 } else if ((offset + rectangle.y) < ((gint) vadj->value)) {
549 new_value = (offset + rectangle.y - vadj->page_size * 0.75);
550 if (((gint) (new_value + vadj->page_size)) < (offset + rectangle.y + rectangle.height))
551 new_value = offset + rectangle.y + rectangle.height - (gint) vadj->page_size;
554 if (new_value > vadj->value)
555 new_value = vadj->value;
558 if (vadj->value != new_value) {
559 g_signal_emit_by_name (GTK_TEXT_VIEW(priv->msg_body)->layout,
561 vadj->value = new_value;
562 gtk_adjustment_value_changed (vadj);
563 /* invalidate body */
564 window = gtk_widget_get_parent_window (priv->msg_body);
566 gdk_window_invalidate_rect (window, NULL, TRUE);
572 correct_scroll (ModestMsgEditWindow *w)
574 ModestMsgEditWindowPrivate *priv;
576 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
577 if (gtk_grab_get_current () == priv->msg_body) {
578 if (priv->scroll_drag_timeout_id == 0) {
579 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
585 correct_scroll_without_drag_check (w, TRUE);
589 text_buffer_end_user_action (GtkTextBuffer *buffer,
590 ModestMsgEditWindow *userdata)
593 correct_scroll (userdata);
597 text_buffer_mark_set (GtkTextBuffer *buffer,
600 ModestMsgEditWindow *userdata)
602 gtk_text_buffer_begin_user_action (buffer);
603 gtk_text_buffer_end_user_action (buffer);
607 cut_clipboard_check (GtkTextView *text_view,
610 GtkTextBuffer *buffer;
612 buffer = gtk_text_view_get_buffer (text_view);
613 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
614 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
619 copy_clipboard_check (GtkTextView *text_view,
622 GtkTextBuffer *buffer;
624 buffer = gtk_text_view_get_buffer (text_view);
625 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
626 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
631 vadj_changed (GtkAdjustment *adj,
632 ModestMsgEditWindow *window)
634 ModestMsgEditWindowPrivate *priv;
636 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
638 if (priv->last_upper != adj->upper) {
639 priv->last_upper = adj->upper;
640 correct_scroll (window);
645 attachment_deleted (ModestAttachmentsView *attachments_view,
648 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
653 connect_signals (ModestMsgEditWindow *obj)
655 ModestMsgEditWindowPrivate *priv;
657 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
659 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
660 G_CALLBACK (text_buffer_refresh_attributes), obj);
661 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
662 G_CALLBACK (text_buffer_can_undo), obj);
663 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
664 G_CALLBACK (text_buffer_can_redo), obj);
665 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
666 G_CALLBACK (body_changed), obj);
667 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
668 G_CALLBACK (body_changed), obj);
669 g_signal_connect (G_OBJECT (obj), "window-state-event",
670 G_CALLBACK (modest_msg_edit_window_window_state_event),
672 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
673 G_CALLBACK (text_buffer_end_user_action), obj);
674 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
675 G_CALLBACK (text_buffer_mark_set), obj);
676 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
677 G_CALLBACK (text_buffer_apply_tag), obj);
678 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
679 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
680 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
681 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
682 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
683 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
685 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
686 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
688 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
689 G_CALLBACK (msg_body_focus), obj);
690 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
691 G_CALLBACK (msg_body_focus), obj);
692 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
693 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
694 "changed", G_CALLBACK (recpt_field_changed), obj);
695 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
696 "changed", G_CALLBACK (recpt_field_changed), obj);
697 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
698 "changed", G_CALLBACK (recpt_field_changed), obj);
699 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
700 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
701 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
703 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
704 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
706 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
708 G_CALLBACK (vadj_changed),
711 priv->clipboard_change_handler_id =
712 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
713 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
714 priv->default_clipboard_change_handler_id =
715 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
716 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
718 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
719 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
720 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
724 init_window (ModestMsgEditWindow *obj)
726 GtkWidget *from_caption, *to_caption, *subject_caption;
727 GtkWidget *main_vbox;
728 ModestMsgEditWindowPrivate *priv;
729 GtkActionGroup *action_group;
730 ModestWindowPrivate *parent_priv;
731 GdkPixbuf *window_icon = NULL;
732 GError *error = NULL;
734 GtkSizeGroup *size_group;
735 GtkWidget *subject_box;
736 GtkWidget *attachment_icon;
737 GtkWidget *window_box;
738 #if (GTK_MINOR_VERSION >= 10)
739 GdkAtom deserialize_type;
741 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
742 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
744 parent_priv->ui_manager = gtk_ui_manager_new();
745 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
746 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
748 /* Add common actions */
749 gtk_action_group_add_actions (action_group,
750 modest_msg_edit_action_entries,
751 G_N_ELEMENTS (modest_msg_edit_action_entries),
753 gtk_action_group_add_toggle_actions (action_group,
754 modest_msg_edit_toggle_action_entries,
755 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
757 gtk_action_group_add_radio_actions (action_group,
758 modest_msg_edit_alignment_radio_action_entries,
759 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
761 G_CALLBACK (modest_ui_actions_on_change_justify),
763 gtk_action_group_add_radio_actions (action_group,
764 modest_msg_edit_priority_action_entries,
765 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
767 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
769 gtk_action_group_add_radio_actions (action_group,
770 modest_msg_edit_file_format_action_entries,
771 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
772 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
773 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
775 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
776 g_object_unref (action_group);
778 /* Load the UI definition */
779 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
782 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
783 g_clear_error (&error);
786 /* Add accelerators */
787 gtk_window_add_accel_group (GTK_WINDOW (obj),
788 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
790 parent_priv->menubar = NULL;
792 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
794 /* Note: This ModestPairList* must exist for as long as the combo
795 * that uses it, because the ModestComboBox uses the ID opaquely,
796 * so it can't know how to manage its memory. */
797 priv->from_field = modest_combo_box_new (NULL, g_str_equal);
799 priv->to_field = modest_recpt_editor_new ();
800 priv->cc_field = modest_recpt_editor_new ();
801 priv->bcc_field = modest_recpt_editor_new ();
802 subject_box = gtk_hbox_new (FALSE, 0);
803 priv->priority_icon = gtk_image_new ();
804 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
805 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
806 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
807 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
808 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
809 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
810 priv->add_attachment_button = gtk_button_new ();
811 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
812 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
813 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
814 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
815 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
816 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
817 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
818 priv->attachments_view = modest_attachments_view_new (NULL);
820 priv->header_box = gtk_vbox_new (FALSE, 0);
822 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
823 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
824 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
825 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
826 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
827 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
828 g_object_unref (size_group);
830 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
831 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
832 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
833 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
834 gtk_size_group_add_widget (size_group, priv->subject_field);
835 gtk_size_group_add_widget (size_group, priv->attachments_view);
836 g_object_unref (size_group);
838 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
839 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
840 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
841 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
842 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
843 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
844 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
847 priv->msg_body = wp_text_view_new ();
848 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
849 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
850 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
851 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
852 #if (GTK_MINOR_VERSION >= 10)
853 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
854 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
856 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
857 deserialize_type, TRUE);
859 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
861 priv->find_toolbar = hildon_find_toolbar_new (NULL);
862 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
864 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
866 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
867 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
868 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
869 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
871 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
873 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
874 priv->frame = gtk_frame_new (NULL);
875 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
877 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
878 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
879 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
881 window_box = gtk_vbox_new (FALSE, 0);
882 gtk_container_add (GTK_CONTAINER(obj), window_box);
884 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
886 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
888 /* Set window icon */
889 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
891 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
892 g_object_unref (window_icon);
897 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
899 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
901 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
902 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
903 priv->clipboard_change_handler_id))
904 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
905 priv->clipboard_change_handler_id);
906 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
907 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
908 priv->default_clipboard_change_handler_id))
909 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
910 priv->default_clipboard_change_handler_id);
912 if (priv->account_removed_handler_id &&
913 g_signal_handler_is_connected (modest_runtime_get_account_store (),
914 priv->account_removed_handler_id))
915 g_signal_handler_disconnect(modest_runtime_get_account_store (),
916 priv->account_removed_handler_id);
920 modest_msg_edit_window_finalize (GObject *obj)
922 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
924 /* Sanity check: shouldn't be needed, the window mgr should
925 call this function before */
926 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
928 if (priv->font_dialog != NULL) {
929 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
932 if (priv->clipboard_text != NULL) {
933 g_free (priv->clipboard_text);
934 priv->clipboard_text = NULL;
937 if (priv->draft_msg != NULL) {
938 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
939 if (TNY_IS_HEADER (header)) {
940 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
941 modest_window_mgr_unregister_header (mgr, header);
943 g_object_unref (priv->draft_msg);
944 priv->draft_msg = NULL;
946 if (priv->outbox_msg != NULL) {
947 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
948 if (TNY_IS_HEADER (header)) {
949 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
950 modest_window_mgr_unregister_header (mgr, header);
952 g_object_unref (priv->outbox_msg);
953 priv->outbox_msg = NULL;
955 if (priv->scroll_drag_timeout_id > 0) {
956 g_source_remove (priv->scroll_drag_timeout_id);
957 priv->scroll_drag_timeout_id = 0;
959 if (priv->clipboard_owner_idle > 0) {
960 g_source_remove (priv->clipboard_owner_idle);
961 priv->clipboard_owner_idle = 0;
963 if (priv->original_account_name)
964 g_free (priv->original_account_name);
965 g_free (priv->msg_uid);
966 g_free (priv->last_search);
967 g_slist_free (priv->font_items_group);
968 g_slist_free (priv->size_items_group);
969 g_object_unref (priv->attachments);
970 g_object_unref (priv->images);
972 /* This had to stay alive for as long as the combobox that used it: */
973 modest_pair_list_free (priv->from_field_protos);
975 G_OBJECT_CLASS(parent_class)->finalize (obj);
979 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
981 GdkPixbufLoader *loader;
987 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
989 if (loader == NULL) {
995 tny_stream_reset (TNY_STREAM (stream));
996 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
997 GError *error = NULL;
998 unsigned char read_buffer[128];
1000 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1002 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1007 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1009 g_object_ref (pixbuf);
1010 gdk_pixbuf_loader_close (loader, NULL);
1011 g_object_unref (loader);
1016 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1017 GdkPixbuf *new_pixbuf;
1019 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1020 gdk_pixbuf_get_width (pixbuf);
1021 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1022 g_object_unref (pixbuf);
1023 pixbuf = new_pixbuf;
1027 *stream_size = size;
1033 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1035 ModestMsgEditWindowPrivate *priv;
1038 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1040 for (iter = tny_list_create_iterator (attachments);
1041 !tny_iterator_is_done (iter);
1042 tny_iterator_next (iter)) {
1043 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1044 const gchar *cid = tny_mime_part_get_content_id (part);
1045 const gchar *mime_type = tny_mime_part_get_content_type (part);
1046 if ((cid != NULL)&&(mime_type != NULL)) {
1047 guint64 stream_size;
1048 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1049 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1052 g_object_unref (stream);
1054 if (pixbuf != NULL) {
1055 priv->images_count ++;
1056 priv->images_size += stream_size;
1057 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1058 g_object_unref (pixbuf);
1061 g_object_unref (part);
1063 g_object_unref (iter);
1067 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1069 TnyMimePart *parent = NULL;
1070 const gchar *content_type = NULL;
1071 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1073 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1075 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1076 parent = g_object_ref (msg);
1077 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1078 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1081 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1082 iter = tny_list_create_iterator (parts);
1083 while (!tny_iterator_is_done (iter)) {
1085 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1086 content_type = tny_mime_part_get_content_type (part);
1087 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1091 g_object_unref (part);
1093 tny_iterator_next (iter);
1095 g_object_unref (iter);
1096 g_object_unref (parts);
1099 if (parent != NULL) {
1100 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1103 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1104 iter = tny_list_create_iterator (parts);
1105 while (!tny_iterator_is_done (iter)) {
1107 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1108 content_type = tny_mime_part_get_content_type (part);
1109 if (content_type && g_str_has_prefix (content_type, "image/")) {
1110 tny_list_prepend (priv->images, (GObject *) part);
1112 g_object_unref (part);
1113 tny_iterator_next (iter);
1115 g_object_unref (iter);
1116 g_object_unref (parts);
1117 g_object_unref (parent);
1122 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1125 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1127 for (iter = tny_list_create_iterator (attachments) ;
1128 !tny_iterator_is_done (iter);
1129 tny_iterator_next (iter)) {
1130 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1131 const gchar *cid = tny_mime_part_get_content_id (part);
1133 char *invalid = NULL;
1134 gint int_cid = strtol (cid, &invalid, 10);
1135 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1136 priv->next_cid = int_cid + 1;
1139 g_object_unref (part);
1141 g_object_unref (iter);
1145 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1148 gchar *to, *cc, *bcc, *subject;
1150 ModestMsgEditWindowPrivate *priv;
1152 TnyHeaderFlags priority_flags;
1153 TnyFolder *msg_folder;
1154 gboolean is_html = FALSE;
1156 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1157 g_return_if_fail (TNY_IS_MSG (msg));
1159 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1161 header = tny_msg_get_header (msg);
1162 to = tny_header_dup_to (header);
1163 cc = tny_header_dup_cc (header);
1164 bcc = tny_header_dup_bcc (header);
1165 subject = tny_header_dup_subject (header);
1166 priority_flags = tny_header_get_priority (header);
1169 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1171 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1172 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1173 gtk_widget_show (priv->cc_caption);
1174 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1175 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1176 gtk_widget_hide (priv->cc_caption);
1179 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1180 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1181 gtk_widget_show (priv->bcc_caption);
1182 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1183 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1184 gtk_widget_hide (priv->bcc_caption);
1187 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1188 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1191 update_window_title (self);
1193 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1194 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1196 if ((body == NULL)||(body[0] == '\0')) {
1198 body = modest_text_utils_convert_to_html ("");
1201 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1202 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1205 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1208 /* Add attachments to the view */
1209 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1210 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1211 if (tny_list_get_length (priv->attachments) == 0) {
1212 gtk_widget_hide (priv->attachments_caption);
1214 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1215 gtk_widget_show_all (priv->attachments_caption);
1217 get_related_images (self, msg);
1218 update_next_cid (self, priv->attachments);
1219 update_next_cid (self, priv->images);
1220 replace_with_images (self, priv->images);
1222 if (preserve_is_rich && !is_html) {
1223 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1224 /* Get the default format required from configuration */
1225 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1226 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1229 /* Set the default focus depending on having already a To: field or not */
1230 if ((!to)||(*to == '\0')) {
1231 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1233 gtk_widget_grab_focus (priv->msg_body);
1236 /* TODO: lower priority, select in the From: combo to the
1237 value that comes from msg <- not sure, should it be
1240 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1242 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1243 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1245 modest_msg_edit_window_set_modified (self, FALSE);
1247 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1248 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1249 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1250 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1252 if (priv->msg_uid) {
1253 g_free (priv->msg_uid);
1254 priv->msg_uid = NULL;
1257 /* we should set a reference to the incoming message if it is a draft */
1258 msg_folder = tny_msg_get_folder (msg);
1260 if (modest_tny_folder_is_local_folder (msg_folder)) {
1261 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1262 if (type == TNY_FOLDER_TYPE_INVALID)
1263 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1265 if (type == TNY_FOLDER_TYPE_DRAFTS)
1266 priv->draft_msg = g_object_ref(msg);
1267 if (type == TNY_FOLDER_TYPE_OUTBOX)
1268 priv->outbox_msg = g_object_ref(msg);
1269 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1271 g_object_unref (msg_folder);
1281 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1284 GList *item_children, *node;
1285 GtkWidget *bin_child;
1287 bin_child = gtk_bin_get_child (GTK_BIN(item));
1289 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1291 for (node = item_children; node != NULL; node = g_list_next (node)) {
1292 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1293 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1296 g_list_free (item_children);
1300 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1303 GList *item_children, *node;
1305 box = gtk_bin_get_child (GTK_BIN (item));
1306 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1307 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1309 for (node = item_children; node != NULL; node = g_list_next (node)) {
1310 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1311 if (GTK_IS_TOGGLE_BUTTON (node->data))
1312 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1313 else if (GTK_IS_BUTTON (node->data))
1314 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1316 g_list_free (item_children);
1321 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1323 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1324 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1325 GtkWidget *placeholder;
1326 GtkWidget *tool_item;
1331 GtkWidget *sizes_menu;
1332 GtkWidget *fonts_menu;
1333 GSList *radio_group = NULL;
1334 GSList *node = NULL;
1338 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1339 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1341 /* Font color placeholder */
1342 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1343 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1346 tool_item = GTK_WIDGET (gtk_tool_item_new ());
1347 priv->font_color_button = hildon_color_button_new ();
1348 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1349 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1350 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
1351 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1352 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1353 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1354 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1356 G_CALLBACK (modest_msg_edit_window_color_button_change),
1359 /* Font size and face placeholder */
1360 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1361 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1363 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1364 priv->size_tool_button_label = gtk_label_new (NULL);
1365 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1366 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1367 size_text,"</span>", NULL);
1368 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1370 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1371 sizes_menu = gtk_menu_new ();
1372 priv->size_items_group = NULL;
1374 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1375 GtkWidget *size_menu_item;
1377 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1378 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1379 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1380 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1381 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1382 gtk_widget_show (size_menu_item);
1384 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1388 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1389 GtkWidget *item = (GtkWidget *) node->data;
1390 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1394 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1395 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1396 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1397 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1398 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1399 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1400 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1401 priv->font_size_toolitem = tool_item;
1404 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1405 priv->font_tool_button_label = gtk_label_new (NULL);
1406 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1407 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1409 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1410 fonts_menu = gtk_menu_new ();
1411 priv->font_items_group = NULL;
1413 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1414 GtkWidget *font_menu_item;
1415 GtkWidget *child_label;
1417 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1418 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1419 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1420 wp_get_font_name (font_index), "</span>", NULL);
1421 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1424 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1425 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1426 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1427 gtk_widget_show (font_menu_item);
1429 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1432 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1433 GtkWidget *item = (GtkWidget *) node->data;
1434 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1437 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1438 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1439 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1440 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1441 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1442 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1443 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1444 priv->font_face_toolitem = tool_item;
1446 /* Set expand and homogeneous for remaining items */
1447 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1448 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1449 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1450 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1451 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1452 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1453 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1454 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1455 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1457 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1458 will not show the tool items added to the placeholders) */
1459 gtk_widget_show_all (parent_priv->toolbar);
1461 /* Set the no show all *after* showing all items. We do not
1462 want the toolbar to be shown with a show all because it
1463 could go agains the gconf setting regarding showing or not
1464 the toolbar of the editor window */
1465 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1471 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1474 ModestWindowPrivate *parent_priv;
1475 ModestMsgEditWindowPrivate *priv;
1476 ModestDimmingRulesGroup *menu_rules_group = NULL;
1477 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1478 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1479 ModestWindowMgr *mgr = NULL;
1481 g_return_val_if_fail (msg, NULL);
1482 g_return_val_if_fail (account_name, NULL);
1484 mgr = modest_runtime_get_window_mgr ();
1486 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1488 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1489 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1491 /* Menubar. Update the state of some toggles */
1492 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1493 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1494 priv->from_field_protos = get_transports ();
1495 modest_combo_box_set_pair_list (MODEST_COMBO_BOX (priv->from_field), priv->from_field_protos);
1496 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), (gpointer) account_name);
1497 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1498 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1501 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1503 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1505 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1507 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1509 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1510 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1511 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1512 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1513 /* Add common dimming rules */
1514 modest_dimming_rules_group_add_rules (menu_rules_group,
1515 modest_msg_edit_window_menu_dimming_entries,
1516 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1517 MODEST_WINDOW (obj));
1518 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1519 modest_msg_edit_window_toolbar_dimming_entries,
1520 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1521 MODEST_WINDOW (obj));
1522 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1523 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1524 MODEST_WINDOW (obj));
1525 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1526 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1527 MODEST_WINDOW (obj));
1528 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1529 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1530 MODEST_WINDOW (obj));
1531 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1532 modest_msg_edit_window_clipboard_dimming_entries,
1533 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1534 MODEST_WINDOW (obj));
1535 /* Insert dimming rules group for this window */
1536 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1537 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1538 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1539 /* Checks the dimming rules */
1540 g_object_unref (menu_rules_group);
1541 g_object_unref (toolbar_rules_group);
1542 g_object_unref (clipboard_rules_group);
1543 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1545 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1547 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1548 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1549 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1550 priv->update_caption_visibility = TRUE;
1552 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1554 /* Track account-removed signal, this window should be closed
1555 in the case we're creating a mail associated to the account
1557 priv->account_removed_handler_id =
1558 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1560 G_CALLBACK(on_account_removed),
1563 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1565 return (ModestWindow*) obj;
1569 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1571 GString **string_buffer = (GString **) user_data;
1573 *string_buffer = g_string_append (*string_buffer, buffer);
1579 * @result: A new string which should be freed with g_free().
1582 get_formatted_data (ModestMsgEditWindow *edit_window)
1584 ModestMsgEditWindowPrivate *priv;
1585 GString *string_buffer = g_string_new ("");
1587 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1589 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1591 modest_text_utils_hyperlinkify (string_buffer);
1593 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1595 return g_string_free (string_buffer, FALSE);
1600 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1603 const gchar *account_name;
1604 ModestMsgEditWindowPrivate *priv;
1605 TnyIterator *att_iter;
1607 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1609 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1611 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1612 g_return_val_if_fail (account_name, NULL);
1615 /* don't free these (except from) */
1616 data = g_slice_new0 (MsgData);
1617 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1619 data->account_name = g_strdup (account_name);
1620 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1621 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1622 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1623 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1624 if (priv->draft_msg) {
1625 data->draft_msg = g_object_ref (priv->draft_msg);
1626 } else if (priv->outbox_msg) {
1627 data->draft_msg = g_object_ref (priv->outbox_msg);
1629 data->draft_msg = NULL;
1632 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1634 gtk_text_buffer_get_bounds (buf, &b, &e);
1635 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1637 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1638 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1640 data->html_body = NULL;
1642 /* deep-copy the data */
1643 att_iter = tny_list_create_iterator (priv->attachments);
1644 data->attachments = NULL;
1645 while (!tny_iterator_is_done (att_iter)) {
1646 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1647 if (!(TNY_IS_MIME_PART(part))) {
1648 g_warning ("strange data in attachment list");
1649 g_object_unref (part);
1650 tny_iterator_next (att_iter);
1653 data->attachments = g_list_append (data->attachments,
1655 tny_iterator_next (att_iter);
1657 g_object_unref (att_iter);
1659 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1660 att_iter = tny_list_create_iterator (priv->images);
1661 data->images = NULL;
1662 while (!tny_iterator_is_done (att_iter)) {
1663 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1665 if (!(TNY_IS_MIME_PART(part))) {
1666 g_warning ("strange data in attachment list");
1667 g_object_unref (part);
1668 tny_iterator_next (att_iter);
1671 cid = tny_mime_part_get_content_id (part);
1673 gchar *image_tag_id;
1674 GtkTextTag *image_tag;
1676 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1677 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1678 g_free (image_tag_id);
1680 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1682 ((gtk_text_iter_has_tag (&iter, image_tag))||
1683 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1684 data->images = g_list_append (data->images,
1685 g_object_ref (part));
1687 g_object_unref (part);
1688 tny_iterator_next (att_iter);
1690 g_object_unref (att_iter);
1692 data->priority_flags = priv->priority_flags;
1699 unref_gobject (GObject *obj, gpointer data)
1701 if (!G_IS_OBJECT(obj))
1703 g_object_unref (obj);
1707 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1710 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1718 g_free (data->from);
1719 g_free (data->subject);
1720 g_free (data->plain_body);
1721 g_free (data->html_body);
1722 g_free (data->account_name);
1724 if (data->draft_msg != NULL) {
1725 g_object_unref (data->draft_msg);
1726 data->draft_msg = NULL;
1729 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1730 g_list_free (data->attachments);
1731 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1732 g_list_free (data->images);
1734 g_slice_free (MsgData, data);
1738 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1740 guint64 *parts_size)
1742 ModestMsgEditWindowPrivate *priv;
1744 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1746 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1748 /* TODO: add images */
1749 *parts_size += priv->images_size;
1750 *parts_count += priv->images_count;
1755 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1758 ModestMsgEditWindowPrivate *priv = NULL;
1759 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1761 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1763 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1765 return MODEST_MSG_EDIT_FORMAT_HTML;
1767 return MODEST_MSG_EDIT_FORMAT_TEXT;
1771 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1772 ModestMsgEditFormat format)
1774 ModestMsgEditWindowPrivate *priv;
1776 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1777 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1780 case MODEST_MSG_EDIT_FORMAT_HTML:
1781 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1783 case MODEST_MSG_EDIT_FORMAT_TEXT:
1784 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1787 g_return_if_reached ();
1791 ModestMsgEditFormatState *
1792 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1794 ModestMsgEditFormatState *format_state = NULL;
1795 ModestMsgEditWindowPrivate *priv;
1796 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1798 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1799 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1801 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1803 format_state = g_new0 (ModestMsgEditFormatState, 1);
1804 format_state->bold = buffer_format->bold&0x1;
1805 format_state->italics = buffer_format->italic&0x1;
1806 format_state->bullet = buffer_format->bullet&0x1;
1807 format_state->color = buffer_format->color;
1808 format_state->font_size = buffer_format->font_size;
1809 format_state->font_family = wp_get_font_name (buffer_format->font);
1810 format_state->justification = buffer_format->justification;
1811 g_free (buffer_format);
1813 return format_state;
1818 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1819 const ModestMsgEditFormatState *format_state)
1821 ModestMsgEditWindowPrivate *priv;
1822 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1823 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1824 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1825 g_return_if_fail (format_state != NULL);
1827 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1828 gtk_widget_grab_focus (priv->msg_body);
1829 buffer_format->bold = (format_state->bold != FALSE);
1830 buffer_format->italic = (format_state->italics != FALSE);
1831 buffer_format->color = format_state->color;
1832 buffer_format->font_size = format_state->font_size;
1833 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1834 buffer_format->justification = format_state->justification;
1835 buffer_format->bullet = format_state->bullet;
1837 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1839 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1840 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1841 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1842 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1843 buffer_format->cs.font = (buffer_format->font != current_format->font);
1844 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1845 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1847 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1848 if (buffer_format->cs.bold) {
1849 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1850 GINT_TO_POINTER (buffer_format->bold&0x1));
1852 if (buffer_format->cs.italic) {
1853 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1854 GINT_TO_POINTER (buffer_format->italic&0x1));
1856 if (buffer_format->cs.color) {
1857 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1858 GINT_TO_POINTER (&(buffer_format->color)));
1860 if (buffer_format->cs.font_size) {
1861 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1862 GINT_TO_POINTER (buffer_format->font_size));
1864 if (buffer_format->cs.justification) {
1865 switch (buffer_format->justification) {
1866 case GTK_JUSTIFY_LEFT:
1867 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1868 GINT_TO_POINTER(TRUE));
1870 case GTK_JUSTIFY_CENTER:
1871 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1872 GINT_TO_POINTER(TRUE));
1874 case GTK_JUSTIFY_RIGHT:
1875 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1876 GINT_TO_POINTER(TRUE));
1883 if (buffer_format->cs.font) {
1884 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1885 GINT_TO_POINTER (buffer_format->font));
1887 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1888 if (buffer_format->cs.bullet) {
1889 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1890 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1892 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1894 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1896 g_free (current_format);
1898 /* Check dimming rules */
1899 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1900 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1904 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1906 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1908 ModestWindowPrivate *parent_priv;
1909 ModestMsgEditWindowPrivate *priv;
1910 GtkWidget *new_size_menuitem;
1911 GtkWidget *new_font_menuitem;
1913 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1914 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1916 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1917 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1918 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1919 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1921 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1922 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1923 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1926 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1928 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1929 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1931 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1932 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1934 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1935 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1938 switch (buffer_format->justification)
1940 case GTK_JUSTIFY_LEFT:
1941 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1943 case GTK_JUSTIFY_CENTER:
1944 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1946 case GTK_JUSTIFY_RIGHT:
1947 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1954 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1956 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1957 G_CALLBACK (modest_msg_edit_window_color_button_change),
1959 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1960 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1961 G_CALLBACK (modest_msg_edit_window_color_button_change),
1964 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1965 buffer_format->font_size))->data);
1966 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1970 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1971 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1972 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1974 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1975 G_CALLBACK (modest_msg_edit_window_size_change),
1977 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1978 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1979 G_CALLBACK (modest_msg_edit_window_size_change),
1983 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1984 buffer_format->font))->data);
1985 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1989 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1990 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1991 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1993 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1994 G_CALLBACK (modest_msg_edit_window_font_change),
1996 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1997 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1998 G_CALLBACK (modest_msg_edit_window_font_change),
2002 g_free (buffer_format);
2006 #ifdef MODEST_HILDON_VERSION_0
2008 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2011 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2012 ModestMsgEditWindowPrivate *priv;
2013 GtkWidget *dialog = NULL;
2015 GdkColor *new_color = NULL;
2017 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2018 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2020 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2021 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2022 g_free (buffer_format);
2024 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2025 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2026 if (new_color != NULL) {
2027 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2028 (gpointer) new_color);
2031 gtk_widget_destroy (dialog);
2036 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2039 ModestMsgEditWindowPrivate *priv;
2040 GtkWidget *dialog = NULL;
2042 GdkColor *old_color = NULL;
2043 const GdkColor *new_color = NULL;
2045 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2046 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2048 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2049 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2051 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2052 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2053 if (new_color != NULL)
2054 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2056 gtk_widget_destroy (dialog);
2062 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2065 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2066 ModestMsgEditWindowPrivate *priv;
2067 GtkWidget *dialog = NULL;
2069 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2070 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2072 dialog = hildon_color_chooser_new ();
2073 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2074 g_free (buffer_format);
2076 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2078 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2079 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2082 gtk_widget_destroy (dialog);
2087 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2090 ModestMsgEditWindowPrivate *priv;
2091 GtkWidget *dialog = NULL;
2092 GdkColor *old_color = NULL;
2094 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2095 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2097 dialog = hildon_color_chooser_new ();
2098 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2100 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2102 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2103 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2105 gtk_widget_destroy (dialog);
2108 #endif /*!MODEST_HILDON_VERSION_0*/
2113 create_stream_for_uri (const gchar* uri)
2118 TnyStream *result = NULL;
2120 GnomeVFSHandle *handle = NULL;
2121 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2122 if (test == GNOME_VFS_OK) {
2123 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2124 /* Streams over OBEX (Bluetooth) are not seekable but
2125 * we expect them to be (we might need to read them
2126 * several times). So if this is a Bluetooth URI just
2127 * read the whole file into memory (this is not a fast
2128 * protocol so we can assume that these files are not
2129 * going to be very big) */
2130 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2131 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2132 TnyStream *memstream = tny_camel_mem_stream_new ();
2133 tny_stream_write_to_stream (vfssstream, memstream);
2134 g_object_unref (vfssstream);
2137 result = vfssstream;
2145 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2148 ModestMsgEditWindowPrivate *priv;
2149 GtkWidget *dialog = NULL;
2151 GSList *uris = NULL;
2152 GSList *uri_node = NULL;
2154 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2156 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2157 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2158 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2160 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2162 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2163 GTK_WINDOW (dialog));
2165 response = gtk_dialog_run (GTK_DIALOG (dialog));
2167 case GTK_RESPONSE_OK:
2168 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2173 gtk_widget_destroy (dialog);
2175 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2177 GnomeVFSHandle *handle = NULL;
2178 GnomeVFSResult result;
2179 GtkTextIter position;
2180 GtkTextMark *insert_mark;
2182 uri = (const gchar *) uri_node->data;
2183 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2184 if (result == GNOME_VFS_OK) {
2186 GnomeVFSFileInfo *info;
2187 gchar *filename, *basename, *escaped_filename;
2188 TnyMimePart *mime_part;
2190 const gchar *mime_type = NULL;
2191 GnomeVFSURI *vfs_uri;
2192 guint64 stream_size;
2194 gnome_vfs_close (handle);
2195 vfs_uri = gnome_vfs_uri_new (uri);
2197 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2198 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2199 g_free (escaped_filename);
2200 gnome_vfs_uri_unref (vfs_uri);
2201 info = gnome_vfs_file_info_new ();
2203 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2204 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2206 mime_type = gnome_vfs_file_info_get_mime_type (info);
2208 mime_part = tny_platform_factory_new_mime_part
2209 (modest_runtime_get_platform_factory ());
2211 TnyStream *stream = create_stream_for_uri (uri);
2213 if (stream == NULL) {
2215 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2217 g_object_unref (mime_part);
2218 gnome_vfs_file_info_unref (info);
2222 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2224 content_id = g_strdup_printf ("%d", priv->next_cid);
2225 tny_mime_part_set_content_id (mime_part, content_id);
2226 g_free (content_id);
2229 basename = g_path_get_basename (filename);
2230 tny_mime_part_set_filename (mime_part, basename);
2233 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2235 if (pixbuf != NULL) {
2236 priv->images_size += stream_size;
2237 priv->images_count ++;
2238 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2239 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2240 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2243 tny_list_prepend (priv->images, (GObject *) mime_part);
2244 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2246 g_object_unref (mime_part);
2247 gnome_vfs_file_info_unref (info);
2256 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2258 GtkWidget *dialog = NULL;
2260 GSList *uris = NULL;
2262 GnomeVFSFileSize total_size, allowed_size;
2263 ModestMsgEditWindowPrivate *priv;
2267 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2269 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2271 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2274 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2275 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2276 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2277 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
2279 response = gtk_dialog_run (GTK_DIALOG (dialog));
2281 case GTK_RESPONSE_OK:
2282 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2287 gtk_widget_destroy (dialog);
2289 /* allowed size is the maximum size - what's already there */
2290 modest_attachments_view_get_sizes (
2291 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2292 &att_num, &att_size);
2293 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2296 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2298 const gchar *uri = (const gchar *) uri_node->data;
2300 total_size += modest_msg_edit_window_attach_file_one
2301 (window, uri, allowed_size);
2303 if (total_size > allowed_size) {
2304 g_warning ("%s: total size: %u",
2305 __FUNCTION__, (unsigned int)total_size);
2309 allowed_size -= total_size;
2313 g_slist_foreach (uris, (GFunc) g_free, NULL);
2314 g_slist_free (uris);
2319 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2321 GnomeVFSFileSize allowed_size)
2324 GnomeVFSHandle *handle = NULL;
2325 ModestMsgEditWindowPrivate *priv;
2326 GnomeVFSResult result;
2327 GnomeVFSFileSize size = 0;
2328 g_return_val_if_fail (window, 0);
2329 g_return_val_if_fail (uri, 0);
2331 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2333 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2334 if (result == GNOME_VFS_OK) {
2335 TnyMimePart *mime_part;
2337 const gchar *mime_type = NULL;
2339 gchar *escaped_filename;
2342 GnomeVFSFileInfo *info;
2343 GnomeVFSURI *vfs_uri;
2345 gnome_vfs_close (handle);
2346 vfs_uri = gnome_vfs_uri_new (uri);
2349 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2350 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2351 g_free (escaped_filename);
2352 gnome_vfs_uri_unref (vfs_uri);
2354 info = gnome_vfs_file_info_new ();
2356 if (gnome_vfs_get_file_info (uri,
2358 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2360 mime_type = gnome_vfs_file_info_get_mime_type (info);
2361 mime_part = tny_platform_factory_new_mime_part
2362 (modest_runtime_get_platform_factory ());
2364 /* try to get the attachment's size; this may fail for weird
2365 * file systems, like obex, upnp... */
2366 if (allowed_size != 0 &&
2367 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2369 if (size > allowed_size) {
2370 modest_platform_information_banner (NULL, NULL,
2371 dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2375 g_warning ("%s: could not get attachment size", __FUNCTION__);
2377 stream = create_stream_for_uri (uri);
2379 if (stream == NULL) {
2381 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2383 g_object_unref (mime_part);
2384 gnome_vfs_file_info_unref (info);
2388 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2389 g_object_unref (stream);
2391 content_id = g_strdup_printf ("%d", priv->next_cid);
2392 tny_mime_part_set_content_id (mime_part, content_id);
2393 g_free (content_id);
2396 basename = g_path_get_basename (filename);
2397 tny_mime_part_set_filename (mime_part, basename);
2400 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2401 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2403 info->size == 0, info->size);
2404 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2405 gtk_widget_show_all (priv->attachments_caption);
2406 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2408 g_object_unref (mime_part);
2409 gnome_vfs_file_info_unref (info);
2416 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2419 ModestMsgEditWindowPrivate *priv;
2422 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2423 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2425 if (att_list == NULL) {
2426 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2428 g_object_ref (att_list);
2431 if (tny_list_get_length (att_list) == 0) {
2432 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2434 gboolean dialog_response;
2435 gchar *message = NULL;
2436 gchar *filename = NULL;
2438 if (tny_list_get_length (att_list) == 1) {
2440 iter = tny_list_create_iterator (att_list);
2441 part = (TnyMimePart *) tny_iterator_get_current (iter);
2442 g_object_unref (iter);
2443 if (TNY_IS_MSG (part)) {
2444 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2446 filename = tny_header_dup_subject (header);
2447 g_object_unref (header);
2449 if (filename == NULL) {
2450 filename = g_strdup (_("mail_va_no_subject"));
2453 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2455 g_object_unref (part);
2457 filename = g_strdup ("");
2459 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2460 tny_list_get_length (att_list)), filename);
2463 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2466 if (dialog_response != GTK_RESPONSE_OK) {
2467 g_object_unref (att_list);
2470 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
2472 for (iter = tny_list_create_iterator (att_list);
2473 !tny_iterator_is_done (iter);
2474 tny_iterator_next (iter)) {
2475 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2476 const gchar *att_id;
2477 tny_list_remove (priv->attachments, (GObject *) mime_part);
2479 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2481 if (tny_list_get_length (priv->attachments) == 0)
2482 gtk_widget_hide (priv->attachments_caption);
2483 att_id = tny_mime_part_get_content_id (mime_part);
2485 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2487 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2488 g_object_unref (mime_part);
2490 g_object_unref (iter);
2493 g_object_unref (att_list);
2495 /* if the last attachment has been removed, focus the Subject: field */
2496 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2497 gtk_widget_grab_focus (priv->subject_field);
2501 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2504 ModestMsgEditWindowPrivate *priv;
2505 GdkColor *new_color;
2506 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2508 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2509 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2512 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2514 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2516 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2518 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2523 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2526 ModestMsgEditWindowPrivate *priv;
2527 gint new_size_index;
2528 ModestMsgEditWindow *window;
2531 window = MODEST_MSG_EDIT_WINDOW (userdata);
2532 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2533 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2535 if (gtk_check_menu_item_get_active (menu_item)) {
2537 WPTextBufferFormat format;
2539 memset (&format, 0, sizeof (format));
2540 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2542 label = gtk_bin_get_child (GTK_BIN (menu_item));
2544 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2545 format.cs.font_size = TRUE;
2546 format.cs.text_position = TRUE;
2547 format.cs.font = TRUE;
2548 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2549 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2551 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2552 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2553 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2555 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2556 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2557 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2563 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2566 ModestMsgEditWindowPrivate *priv;
2567 gint new_font_index;
2568 ModestMsgEditWindow *window;
2571 window = MODEST_MSG_EDIT_WINDOW (userdata);
2572 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2573 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2575 if (gtk_check_menu_item_get_active (menu_item)) {
2578 label = gtk_bin_get_child (GTK_BIN (menu_item));
2580 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2582 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2583 GINT_TO_POINTER(new_font_index)))
2584 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2586 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2587 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2588 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2594 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2596 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2597 ModestWindowPrivate *parent_priv;
2598 ModestWindowMgr *mgr;
2599 gboolean is_fullscreen;
2600 GtkAction *fs_toggle_action;
2603 mgr = modest_runtime_get_window_mgr ();
2604 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2606 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2608 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2609 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2610 if (is_fullscreen != active)
2611 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2619 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2622 ModestMsgEditWindowPrivate *priv = NULL;
2623 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2625 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2626 if (!priv->update_caption_visibility)
2629 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2631 gtk_widget_show (priv->cc_caption);
2633 gtk_widget_hide (priv->cc_caption);
2635 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2639 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2642 ModestMsgEditWindowPrivate *priv = NULL;
2643 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2645 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2646 if (!priv->update_caption_visibility)
2649 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2651 gtk_widget_show (priv->bcc_caption);
2653 gtk_widget_hide (priv->bcc_caption);
2655 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2659 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2660 ModestRecptEditor *editor)
2662 ModestMsgEditWindowPrivate *priv;
2664 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2665 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2667 /* we check for low-mem; in that case, show a warning, and don't allow
2668 * for the addressbook
2670 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2673 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2675 if (editor == NULL) {
2676 GtkWidget *view_focus;
2677 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2679 /* This code should be kept in sync with ModestRecptEditor. The
2680 textview inside the recpt editor is the one that really gets the
2681 focus. As it's inside a scrolled window, and this one inside the
2682 hbox recpt editor inherits from, we'll need to go up in the
2683 hierarchy to know if the text view is part of the recpt editor
2684 or if it's a different text entry */
2686 if (gtk_widget_get_parent (view_focus)) {
2687 GtkWidget *first_parent;
2689 first_parent = gtk_widget_get_parent (view_focus);
2690 if (gtk_widget_get_parent (first_parent) &&
2691 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2692 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2697 editor = MODEST_RECPT_EDITOR (priv->to_field);
2701 modest_address_book_select_addresses (editor);
2706 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2708 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2710 modest_msg_edit_window_open_addressbook (window, NULL);
2714 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2715 gboolean show_toolbar)
2717 ModestWindowPrivate *parent_priv;
2718 const gchar *action_name;
2721 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2722 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2724 /* We can not just use the code of
2725 modest_msg_edit_window_setup_toolbar because it has a
2726 mixture of both initialization and creation code. */
2728 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2730 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2732 /* Update also the actions (to update the toggles in the
2733 menus), we have to do it manually because some other window
2734 of the same time could have changed it (remember that the
2735 toolbar fullscreen mode is shared by all the windows of the
2737 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2738 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2740 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2742 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2743 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2749 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2750 TnyHeaderFlags priority_flags)
2752 ModestMsgEditWindowPrivate *priv;
2753 ModestWindowPrivate *parent_priv;
2755 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2757 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2758 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2760 if (priv->priority_flags != priority_flags) {
2761 GtkAction *priority_action = NULL;
2763 priv->priority_flags = priority_flags;
2765 switch (priority_flags) {
2766 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2767 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2768 gtk_widget_show (priv->priority_icon);
2769 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2770 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2772 case TNY_HEADER_FLAG_LOW_PRIORITY:
2773 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2774 gtk_widget_show (priv->priority_icon);
2775 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2776 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2779 gtk_widget_hide (priv->priority_icon);
2780 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2781 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2784 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2785 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2790 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2793 ModestMsgEditWindowPrivate *priv;
2794 ModestWindowPrivate *parent_priv;
2795 gint current_format;
2797 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2799 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2800 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2802 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2803 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2805 if (current_format != file_format) {
2806 switch (file_format) {
2807 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2808 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2809 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2811 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2815 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2816 response = gtk_dialog_run (GTK_DIALOG (dialog));
2817 gtk_widget_destroy (dialog);
2818 if (response == GTK_RESPONSE_OK) {
2819 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2821 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2822 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2827 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2828 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2829 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2834 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2837 ModestMsgEditWindowPrivate *priv;
2838 WPTextBufferFormat oldfmt, fmt;
2839 gint old_position = 0;
2843 GdkColor *color = NULL;
2844 gboolean bold, bold_set, italic, italic_set;
2845 gboolean underline, underline_set;
2846 gboolean strikethrough, strikethrough_set;
2847 gboolean position_set;
2848 gboolean font_size_set, font_set, color_set;
2851 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2852 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2854 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2855 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2856 GTK_WINDOW(dialog));
2858 /* First we get the currently selected font information */
2859 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2861 switch (oldfmt.text_position) {
2862 case TEXT_POSITION_NORMAL:
2865 case TEXT_POSITION_SUPERSCRIPT:
2873 g_object_set (G_OBJECT (dialog),
2874 "bold", oldfmt.bold != FALSE,
2875 "bold-set", !oldfmt.cs.bold,
2876 "underline", oldfmt.underline != FALSE,
2877 "underline-set", !oldfmt.cs.underline,
2878 "italic", oldfmt.italic != FALSE,
2879 "italic-set", !oldfmt.cs.italic,
2880 "strikethrough", oldfmt.strikethrough != FALSE,
2881 "strikethrough-set", !oldfmt.cs.strikethrough,
2882 "color", &oldfmt.color,
2883 "color-set", !oldfmt.cs.color,
2884 "size", wp_font_size[oldfmt.font_size],
2885 "size-set", !oldfmt.cs.font_size,
2886 "position", old_position,
2887 "position-set", !oldfmt.cs.text_position,
2888 "family", wp_get_font_name (oldfmt.font),
2889 "family-set", !oldfmt.cs.font,
2892 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2893 GTK_WINDOW (dialog));
2894 gtk_widget_show_all (dialog);
2895 priv->font_dialog = dialog;
2896 response = gtk_dialog_run (GTK_DIALOG (dialog));
2897 priv->font_dialog = NULL;
2898 if (response == GTK_RESPONSE_OK) {
2900 g_object_get( dialog,
2902 "bold-set", &bold_set,
2903 "underline", &underline,
2904 "underline-set", &underline_set,
2906 "italic-set", &italic_set,
2907 "strikethrough", &strikethrough,
2908 "strikethrough-set", &strikethrough_set,
2910 "color-set", &color_set,
2912 "size-set", &font_size_set,
2913 "family", &font_name,
2914 "family-set", &font_set,
2915 "position", &position,
2916 "position-set", &position_set,
2921 if (response == GTK_RESPONSE_OK) {
2922 memset(&fmt, 0, sizeof(fmt));
2928 fmt.italic = italic;
2929 fmt.cs.italic = TRUE;
2931 if (underline_set) {
2932 fmt.underline = underline;
2933 fmt.cs.underline = TRUE;
2935 if (strikethrough_set) {
2936 fmt.strikethrough = strikethrough;
2937 fmt.cs.strikethrough = TRUE;
2942 ? TEXT_POSITION_NORMAL
2943 : ( ( position == 1 )
2944 ? TEXT_POSITION_SUPERSCRIPT
2945 : TEXT_POSITION_SUBSCRIPT );
2946 fmt.cs.text_position = TRUE;
2947 fmt.font_size = oldfmt.font_size;
2951 fmt.cs.color = TRUE;
2954 fmt.font = wp_get_font_index(font_name,
2959 if (font_size_set) {
2960 fmt.cs.font_size = TRUE;
2961 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2963 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2964 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2966 gtk_widget_destroy (dialog);
2968 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2972 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2974 ModestMsgEditWindowPrivate *priv;
2976 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2977 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2979 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2981 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2982 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2986 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2988 ModestMsgEditWindowPrivate *priv;
2990 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2991 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2993 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2995 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2996 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3001 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3003 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3005 priv->can_undo = can_undo;
3009 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3011 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3013 priv->can_redo = can_redo;
3017 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3019 ModestMsgEditWindowPrivate *priv;
3020 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3021 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3023 return priv->can_undo;
3027 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3029 ModestMsgEditWindowPrivate *priv;
3030 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3031 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3033 return priv->can_redo;
3038 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3041 GtkTextIter match_start, match_end;
3043 if (image_id == NULL)
3046 gtk_text_buffer_get_start_iter (buffer, &iter);
3048 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3049 GSList *tags = gtk_text_iter_get_tags (&match_start);
3051 for (node = tags; node != NULL; node = g_slist_next (node)) {
3052 GtkTextTag *tag = (GtkTextTag *) node->data;
3053 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3054 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3055 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3057 offset = gtk_text_iter_get_offset (&match_start);
3058 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3059 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3063 gtk_text_iter_forward_char (&iter);
3068 message_is_empty (ModestMsgEditWindow *window)
3070 ModestMsgEditWindowPrivate *priv = NULL;
3072 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3073 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3075 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3076 * so we can ignore markup.
3078 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3081 count = gtk_text_buffer_get_char_count (buf);
3087 msg_body_focus (GtkWidget *focus,
3088 GdkEventFocus *event,
3092 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3093 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3094 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3099 recpt_field_changed (GtkTextBuffer *buffer,
3100 ModestMsgEditWindow *editor)
3102 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3103 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3107 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3109 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3110 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3114 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3117 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3118 GtkTextBuffer *buffer;
3120 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3121 gtk_text_buffer_set_modified (buffer, modified);
3122 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3123 gtk_text_buffer_set_modified (buffer, modified);
3124 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3125 gtk_text_buffer_set_modified (buffer, modified);
3126 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3130 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3132 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3133 const char *account_name;
3134 GtkTextBuffer *buffer;
3136 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3137 if (gtk_text_buffer_get_modified (buffer))
3139 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3140 if (gtk_text_buffer_get_modified (buffer))
3142 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3143 if (gtk_text_buffer_get_modified (buffer))
3145 if (gtk_text_buffer_get_modified (priv->text_buffer))
3147 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
3148 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3159 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3161 ModestMsgEditWindowPrivate *priv = NULL;
3163 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3164 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3166 /* check if there's no recipient added */
3167 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3168 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3169 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3170 /* no recipient contents, then select contacts */
3171 modest_msg_edit_window_open_addressbook (window, NULL);
3175 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3176 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3179 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3180 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3183 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3184 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3188 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3189 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3190 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3197 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3198 ModestMsgEditWindow *window)
3200 modest_msg_edit_window_offer_attach_file (window);
3204 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3206 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3208 return priv->clipboard_text;
3212 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3214 ModestMsgEditWindow *window)
3216 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3217 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3219 if (!GTK_WIDGET_VISIBLE (window))
3222 g_object_ref (window);
3223 text = gtk_clipboard_wait_for_text (selection_clipboard);
3225 if (priv->clipboard_text != NULL) {
3226 g_free (priv->clipboard_text);
3228 priv->clipboard_text = text;
3230 if (GTK_WIDGET_VISIBLE (window)) {
3231 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3233 g_object_unref (window);
3236 static gboolean clipboard_owner_change_idle (gpointer userdata)
3238 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3239 ModestMsgEditWindowPrivate *priv;
3241 gdk_threads_enter ();
3242 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3243 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3245 priv->clipboard_owner_idle = 0;
3246 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3247 gdk_threads_leave ();
3253 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3255 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3256 if (priv->clipboard_owner_idle == 0) {
3257 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3262 subject_field_move_cursor (GtkEntry *entry,
3263 GtkMovementStep step,
3268 if (!GTK_WIDGET_VISIBLE (window))
3271 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3275 update_window_title (ModestMsgEditWindow *window)
3277 ModestMsgEditWindowPrivate *priv = NULL;
3278 const gchar *subject;
3280 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3281 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3282 if (subject == NULL || subject[0] == '\0')
3283 subject = _("mail_va_new_email");
3285 gtk_window_set_title (GTK_WINDOW (window), subject);
3290 subject_field_changed (GtkEditable *editable,
3291 ModestMsgEditWindow *window)
3293 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3294 update_window_title (window);
3295 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3296 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3297 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3301 subject_field_insert_text (GtkEditable *editable,
3303 gint new_text_length,
3305 ModestMsgEditWindow *window)
3307 GString *result = g_string_new ("");
3309 gint result_len = 0;
3310 const gchar *entry_text = NULL;
3313 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3314 old_length = g_utf8_strlen (entry_text, -1);
3316 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3317 gunichar c = g_utf8_get_char_validated (current, 8);
3318 /* Invalid unichar, stop */
3324 result = g_string_append_unichar (result, c);
3328 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3329 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3332 /* Prevent endless recursion */
3333 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3334 g_signal_emit_by_name (editable, "insert-text",
3335 (gpointer) result->str, (gpointer) result->len,
3336 (gpointer) position, (gpointer) window);
3337 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3341 if (result_len + old_length > 1000) {
3342 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3343 dgettext("hildon-common-strings",
3344 "ckdg_ib_maximum_characters_reached"));
3347 g_string_free (result, TRUE);
3351 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3354 ModestMsgEditWindowPrivate *priv = NULL;
3356 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3357 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3359 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3362 gtk_widget_show_all (priv->find_toolbar);
3363 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3365 gtk_widget_hide_all (priv->find_toolbar);
3366 gtk_widget_grab_focus (priv->msg_body);
3372 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3374 GtkTextIter *match_start,
3375 GtkTextIter *match_end)
3377 GtkTextIter end_iter;
3378 gchar *str_casefold;
3381 gchar *range_casefold;
3384 gboolean result = FALSE;
3391 gtk_text_iter_forward_to_end (&end_iter);
3393 str_casefold = g_utf8_casefold (str, -1);
3394 str_chars_n = strlen (str);
3396 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3397 range_casefold = g_utf8_casefold (range_text, -1);
3398 range_chars_n = strlen (range_casefold);
3400 if (range_chars_n < str_chars_n) {
3401 g_free (str_casefold);
3402 g_free (range_text);
3403 g_free (range_casefold);
3407 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3408 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3409 if (!g_utf8_collate (range_subtext, str_casefold)) {
3410 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3412 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3413 match_start, match_end, NULL);
3414 g_free (found_text);
3416 g_free (range_subtext);
3420 g_free (str_casefold);
3421 g_free (range_text);
3422 g_free (range_casefold);
3429 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3430 ModestMsgEditWindow *window)
3432 gchar *current_search = NULL;
3433 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3435 GtkTextIter selection_start, selection_end;
3436 GtkTextIter match_start, match_end;
3437 gboolean continue_search = FALSE;
3439 if (message_is_empty (window)) {
3440 g_free (priv->last_search);
3441 priv->last_search = NULL;
3442 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3446 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3447 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3448 g_free (current_search);
3449 g_free (priv->last_search);
3450 priv->last_search = NULL;
3451 /* Information banner about empty search */
3452 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3456 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3457 continue_search = TRUE;
3459 g_free (priv->last_search);
3460 priv->last_search = g_strdup (current_search);
3463 if (continue_search) {
3464 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3465 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3466 &match_start, &match_end);
3468 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3470 GtkTextIter buffer_start;
3471 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3472 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3473 &match_start, &match_end);
3475 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3478 /* Mark as selected the string found in search */
3480 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3481 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3482 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3484 g_free (priv->last_search);
3485 priv->last_search = NULL;
3487 g_free (current_search);
3491 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3492 ModestMsgEditWindow *window)
3494 GtkToggleAction *toggle;
3495 ModestWindowPrivate *parent_priv;
3496 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3498 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3499 gtk_toggle_action_set_active (toggle, FALSE);
3503 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3505 ModestMsgEditWindowPrivate *priv;
3507 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3512 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3515 ModestMsgEditWindowPrivate *priv;
3517 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3523 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3526 ModestMsgEditWindowPrivate *priv;
3527 TnyHeader *header = NULL;
3529 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3530 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3532 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3533 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3535 if (priv->draft_msg != NULL) {
3536 g_object_unref (priv->draft_msg);
3539 if (draft != NULL) {
3540 g_object_ref (draft);
3541 header = tny_msg_get_header (draft);
3542 if (priv->msg_uid) {
3543 g_free (priv->msg_uid);
3544 priv->msg_uid = NULL;
3546 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3547 if (GTK_WIDGET_REALIZED (window))
3548 modest_window_mgr_register_window (mgr, MODEST_WINDOW (window));
3551 priv->draft_msg = draft;
3555 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3556 GtkTextIter *start, GtkTextIter *end,
3559 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3560 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3563 if (tag == NULL+13) return;
3564 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3565 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3566 replace_with_images (window, priv->images);
3571 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3574 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3576 g_return_if_fail (TNY_IS_MIME_PART (part));
3577 tny_list_prepend (priv->attachments, (GObject *) part);
3578 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3579 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3580 gtk_widget_show_all (priv->attachments_caption);
3581 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3585 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3587 ModestMsgEditWindowPrivate *priv;
3589 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3590 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3592 return priv->msg_uid;
3596 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3597 ModestMsgEditWindowWidgetType widget_type)
3599 ModestMsgEditWindowPrivate *priv;
3601 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3602 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3604 switch (widget_type) {
3605 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3606 return priv->msg_body;
3608 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3609 return priv->to_field;
3611 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3612 return priv->cc_field;
3614 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3615 return priv->bcc_field;
3617 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3618 return priv->subject_field;
3620 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3621 return priv->attachments_view;
3629 remove_tags (WPTextBuffer *buffer)
3631 GtkTextIter start, end;
3633 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3634 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3636 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3640 on_account_removed (TnyAccountStore *account_store,
3641 TnyAccount *account,
3644 /* Do nothing if it's a store account, because we use the
3645 transport to send the messages */
3646 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3647 const gchar *parent_acc = NULL;
3648 const gchar *our_acc = NULL;
3650 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3651 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3652 /* Close this window if I'm showing a message of the removed account */
3653 if (strcmp (parent_acc, our_acc) == 0)
3654 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3659 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3661 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3663 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3669 set_zoom_do_nothing (ModestWindow *window,
3675 get_zoom_do_nothing (ModestWindow *window)