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>
39 #include <modest-account-protocol.h>
43 #include <modest-account-mgr.h>
44 #include <modest-account-mgr-helpers.h>
46 #include <widgets/modest-msg-edit-window.h>
47 #include <modest-selector-picker.h>
48 #include <widgets/modest-recpt-editor.h>
49 #include <widgets/modest-attachments-view.h>
51 #include <modest-runtime.h>
53 #include "modest-platform.h"
54 #include "modest-icon-names.h"
55 #include "modest-widget-memory.h"
56 #include "modest-window-priv.h"
57 #include "modest-mail-operation.h"
58 #include "modest-tny-platform-factory.h"
59 #include "modest-tny-msg.h"
60 #include "modest-tny-folder.h"
61 #include "modest-tny-account.h"
62 #include "modest-address-book.h"
63 #include "modest-text-utils.h"
64 #include <tny-simple-list.h>
65 #include <modest-wp-text-view.h>
66 #include <wptextbuffer.h>
67 #include <hildon/hildon-pannable-area.h>
68 #include <hildon/hildon-touch-selector.h>
69 #include <hildon/hildon-picker-dialog.h>
70 #include "modest-msg-edit-window-ui-dimming.h"
72 #include "modest-hildon-includes.h"
73 #ifdef MODEST_HAVE_HILDON0_WIDGETS
74 #include <hildon-widgets/hildon-color-chooser.h>
76 #include "widgets/modest-msg-edit-window-ui.h"
77 #ifdef MODEST_HAVE_HILDON0_WIDGETS
78 #include <libgnomevfs/gnome-vfs-mime-utils.h>
80 #include <libgnomevfs/gnome-vfs-mime.h>
82 #include <modest-utils.h>
83 #include "modest-maemo-utils.h"
84 #include <modest-ui-constants.h>
87 #define DEFAULT_FONT_SIZE 3
88 #define DEFAULT_FONT 2
89 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
90 #define DEFAULT_MAIN_VBOX_SPACING 6
91 #define SUBJECT_MAX_LENGTH 1000
92 #define IMAGE_MAX_WIDTH 560
93 #define DEFAULT_FONT_SCALE 1.5
94 #define ATTACHMENT_BUTTON_WIDTH 118
95 #define MAX_FROM_VALUE 36
96 #define MAX_BODY_LENGTH 4096
98 static gboolean is_wp_text_buffer_started = FALSE;
100 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
101 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
102 static void modest_msg_edit_window_finalize (GObject *obj);
104 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
105 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
106 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
108 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
109 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
110 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
111 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
112 GtkTextIter *start, GtkTextIter *end,
114 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
115 static void body_insert_text (GtkTextBuffer *buffer,
116 GtkTextIter *location,
119 ModestMsgEditWindow *window);
120 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
121 static void subject_field_insert_text (GtkEditable *editable,
123 gint new_text_length,
125 ModestMsgEditWindow *window);
126 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
128 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
130 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
131 ModestRecptEditor *editor);
132 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
133 ModestMsgEditWindow *window);
135 /* ModestWindow methods implementation */
136 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
137 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
138 gboolean show_toolbar);
139 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
141 ModestMsgEditWindow *window);
142 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
143 static void subject_field_move_cursor (GtkEntry *entry,
144 GtkMovementStep step,
148 static void update_window_title (ModestMsgEditWindow *window);
151 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
152 ModestMsgEditWindow *window);
153 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
154 ModestMsgEditWindow *window);
155 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
157 GtkTextIter *match_start,
158 GtkTextIter *match_end);
160 static void remove_tags (WPTextBuffer *buffer);
162 static void on_account_removed (TnyAccountStore *account_store,
166 static void init_window (ModestMsgEditWindow *obj);
168 gboolean scroll_drag_timeout (gpointer userdata);
169 static void correct_scroll (ModestMsgEditWindow *w);
170 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
171 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
172 ModestMsgEditWindow *userdata);
173 static void text_buffer_mark_set (GtkTextBuffer *buffer,
176 ModestMsgEditWindow *userdata);
177 static void on_message_settings (GtkAction *action,
178 ModestMsgEditWindow *window);
179 static void setup_menu (ModestMsgEditWindow *self);
181 static void from_field_changed (HildonPickerButton *button,
182 ModestMsgEditWindow *self);
183 static void font_size_clicked (GtkToolButton *button,
184 ModestMsgEditWindow *window);
185 static void font_face_clicked (GtkToolButton *button,
186 ModestMsgEditWindow *window);
187 static void update_signature (ModestMsgEditWindow *self,
188 const gchar *old_account,
189 const gchar *new_account);
190 static GtkWidget *_create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
191 const gchar *label, GtkWidget *control);
192 static void DEBUG_BUFFER (WPTextBuffer *buffer)
196 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
198 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
199 while (!gtk_text_iter_is_end (&iter)) {
200 GString *output = g_string_new ("");
201 GSList *toggled_tags;
204 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
205 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
206 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
207 GtkTextTag *tag = (GtkTextTag *) node->data;
209 g_object_get (G_OBJECT (tag), "name", &name, NULL);
210 output = g_string_append (output, name);
211 g_string_append (output, " ");
213 output = g_string_append (output, "] OPENED [ ");
214 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
215 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
216 GtkTextTag *tag = (GtkTextTag *) node->data;
218 g_object_get (G_OBJECT (tag), "name", &name, NULL);
219 output = g_string_append (output, name);
220 g_string_append (output, " ");
222 output = g_string_append (output, "]\n");
223 g_message ("%s", output->str);
224 g_string_free (output, TRUE);
225 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
227 g_message ("END BUFFER");
231 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
232 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
236 /* static gboolean */
237 /* on_key_pressed (GtkWidget *self, */
238 /* GdkEventKey *event, */
239 /* gpointer user_data); */
241 /* list my signals */
248 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
249 struct _ModestMsgEditWindowPrivate {
251 GtkWidget *header_box;
253 ModestPairList *from_field_protos;
254 GtkWidget *from_field;
255 gchar *last_from_account;
256 gchar *original_account_name;
261 gchar *original_mailbox;
265 GtkWidget *bcc_field;
266 GtkWidget *subject_field;
267 GtkWidget *attachments_view;
268 GtkWidget *priority_icon;
269 GtkWidget *subject_box;
270 GtkWidget *send_button;
272 GtkWidget *cc_caption;
273 GtkWidget *bcc_caption;
274 gboolean update_caption_visibility;
275 GtkWidget *attachments_caption;
277 GtkTextBuffer *text_buffer;
279 GtkWidget *font_size_toolitem;
280 GtkWidget *font_face_toolitem;
281 GtkWidget *font_color_button;
282 GtkWidget *font_color_toolitem;
283 GSList *font_items_group;
284 GtkTreeModel *faces_model;
285 gint current_face_index;
286 GtkWidget *font_tool_button_label;
287 GtkTreeModel *sizes_model;
288 gint current_size_index;
289 GtkWidget *size_tool_button_label;
291 GtkWidget *find_toolbar;
294 GtkWidget *font_dialog;
297 guint correct_scroll_idle;
298 guint scroll_drag_timeout_id;
302 TnyList *attachments;
307 TnyHeaderFlags priority_flags;
309 gboolean can_undo, can_redo;
310 gulong clipboard_change_handler_id;
311 gulong default_clipboard_change_handler_id;
312 gulong account_removed_handler_id;
313 guint clipboard_owner_idle;
314 gchar *clipboard_text;
323 GtkWidget *cc_button;
324 GtkWidget *bcc_button;
327 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
328 MODEST_TYPE_MSG_EDIT_WINDOW, \
329 ModestMsgEditWindowPrivate))
331 static GtkWindowClass *parent_class = NULL;
333 /* uncomment the following if you have defined any signals */
334 /* static guint signals[LAST_SIGNAL] = {0}; */
337 modest_msg_edit_window_get_type (void)
339 static GType my_type = 0;
341 static const GTypeInfo my_info = {
342 sizeof(ModestMsgEditWindowClass),
343 NULL, /* base init */
344 NULL, /* base finalize */
345 (GClassInitFunc) modest_msg_edit_window_class_init,
346 NULL, /* class finalize */
347 NULL, /* class data */
348 sizeof(ModestMsgEditWindow),
350 (GInstanceInitFunc) modest_msg_edit_window_init,
353 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
354 "ModestMsgEditWindow",
362 save_state (ModestWindow *self)
364 modest_widget_memory_save (modest_runtime_get_conf(),
365 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
370 restore_settings (ModestMsgEditWindow *self)
372 ModestConf *conf = NULL;
374 conf = modest_runtime_get_conf ();
376 /* Dim at start clipboard actions */
377 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
382 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
384 GObjectClass *gobject_class;
385 ModestWindowClass *modest_window_class;
386 gobject_class = (GObjectClass*) klass;
387 modest_window_class = (ModestWindowClass*) klass;
389 parent_class = g_type_class_peek_parent (klass);
390 gobject_class->finalize = modest_msg_edit_window_finalize;
392 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
393 modest_window_class->save_state_func = save_state;
394 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
396 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
400 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
402 ModestMsgEditWindowPrivate *priv;
403 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
405 priv->msg_body = NULL;
406 priv->from_field = NULL;
407 priv->to_field = NULL;
408 priv->cc_field = NULL;
409 priv->bcc_field = NULL;
410 priv->subject_field = NULL;
411 priv->attachments = TNY_LIST (tny_simple_list_new ());
412 priv->images = TNY_LIST (tny_simple_list_new ());
413 priv->images_size = 0;
414 priv->images_count = 0;
417 priv->cc_caption = NULL;
418 priv->bcc_caption = NULL;
419 priv->update_caption_visibility = FALSE;
421 priv->priority_flags = 0;
423 priv->find_toolbar = NULL;
424 priv->last_search = NULL;
426 priv->draft_msg = NULL;
427 priv->outbox_msg = NULL;
428 priv->msg_uid = NULL;
430 priv->can_undo = FALSE;
431 priv->can_redo = FALSE;
432 priv->clipboard_change_handler_id = 0;
433 priv->default_clipboard_change_handler_id = 0;
434 priv->account_removed_handler_id = 0;
435 priv->clipboard_owner_idle = 0;
436 priv->clipboard_text = NULL;
439 priv->scroll_drag_timeout_id = 0;
440 priv->correct_scroll_idle = 0;
441 priv->last_upper = 0.0;
443 priv->font_dialog = NULL;
444 priv->app_menu = NULL;
446 priv->references = NULL;
447 priv->in_reply_to = NULL;
449 if (!is_wp_text_buffer_started) {
450 is_wp_text_buffer_started = TRUE;
451 wp_text_buffer_library_init ();
456 hildon_program_add_window (hildon_program_get_instance(),
461 multimailbox_get_default_mailbox (const gchar *account_name)
463 gchar *transport_account;
464 gchar *result = NULL;
466 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
468 TNY_ACCOUNT_TYPE_TRANSPORT);
469 if (transport_account) {
471 ModestProtocolRegistry *registry;
473 registry = modest_runtime_get_protocol_registry ();
475 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
476 MODEST_ACCOUNT_PROTO, TRUE);
478 ModestProtocol *protocol =
479 modest_protocol_registry_get_protocol_by_name (registry,
480 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
482 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
483 ModestPairList *pair_list;
485 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
488 ModestPair *pair = (ModestPair *) pair_list->data;
489 result = g_strdup ((const gchar *) pair->first);
490 modest_pair_list_free (pair_list);
501 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
503 static ModestPairList*
504 get_transports (void)
506 GSList *transports = NULL;
508 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
509 GSList *accounts = modest_account_mgr_account_names (account_mgr,
510 TRUE /* only enabled accounts. */);
512 GSList *cursor = accounts;
514 gchar *account_name = cursor->data;
517 gchar *transport_account;
518 gboolean multi_mailbox = FALSE;
519 ModestProtocol *protocol = NULL;
521 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
523 transport_account = modest_account_mgr_get_server_account_name
524 (modest_runtime_get_account_mgr (),
526 TNY_ACCOUNT_TYPE_TRANSPORT);
527 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
528 ModestPairList *pair_list;
529 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
532 transports = g_slist_concat (transports, pair_list);
533 multi_mailbox = TRUE;
538 if (!multi_mailbox) {
539 gchar *from_string = NULL;
541 from_string = modest_account_mgr_get_from_string (account_mgr,
543 if (from_string && account_name) {
544 gchar *name = account_name;
545 ModestPair *pair = modest_pair_new ((gpointer) name,
546 (gpointer) from_string , TRUE);
547 transports = g_slist_prepend (transports, pair);
552 cursor = cursor->next;
554 g_slist_free (accounts); /* only free the accounts, not the elements,
555 * because they are used in the pairlist */
559 static void window_focus (GtkWindow *window,
563 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
567 scroll_drag_timeout (gpointer userdata)
569 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
570 ModestMsgEditWindowPrivate *priv;
572 /* It could happen that the window was already closed */
573 if (!GTK_WIDGET_VISIBLE (win))
576 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
578 correct_scroll_without_drag_check (win, TRUE);
580 priv->scroll_drag_timeout_id = 0;
586 correct_scroll_without_drag_check_idle (gpointer userdata)
588 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
589 ModestMsgEditWindowPrivate *priv;
591 GdkRectangle rectangle;
592 gint offset_min, offset_max;
596 /* It could happen that the window was already closed */
597 if (!GTK_WIDGET_VISIBLE (w))
600 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
602 insert = gtk_text_buffer_get_insert (priv->text_buffer);
603 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
605 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
606 offset_min = priv->msg_body->allocation.y + rectangle.y;
607 offset_max = offset_min + rectangle.height;
609 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
610 offset_min = MAX (offset_min - 48, 0);
611 offset_max = MIN (offset_max + 48, vadj->upper);
613 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
615 priv->correct_scroll_idle = 0;
620 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
622 ModestMsgEditWindowPrivate *priv;
624 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
626 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
629 if (priv->correct_scroll_idle > 0) {
633 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
634 (GSourceFunc) correct_scroll_without_drag_check_idle,
640 correct_scroll (ModestMsgEditWindow *w)
642 ModestMsgEditWindowPrivate *priv;
644 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
645 if (gtk_grab_get_current () == priv->msg_body) {
646 if (priv->scroll_drag_timeout_id == 0) {
647 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
649 (GSourceFunc) scroll_drag_timeout,
656 correct_scroll_without_drag_check (w, TRUE);
660 text_buffer_end_user_action (GtkTextBuffer *buffer,
661 ModestMsgEditWindow *userdata)
664 correct_scroll (userdata);
668 text_buffer_mark_set (GtkTextBuffer *buffer,
671 ModestMsgEditWindow *userdata)
673 gtk_text_buffer_begin_user_action (buffer);
674 gtk_text_buffer_end_user_action (buffer);
678 cut_clipboard_check (GtkTextView *text_view,
681 GtkTextBuffer *buffer;
683 buffer = gtk_text_view_get_buffer (text_view);
684 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
685 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
690 copy_clipboard_check (GtkTextView *text_view,
693 GtkTextBuffer *buffer;
695 buffer = gtk_text_view_get_buffer (text_view);
696 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
697 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
702 attachment_deleted (ModestAttachmentsView *attachments_view,
705 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
710 connect_signals (ModestMsgEditWindow *obj)
712 ModestMsgEditWindowPrivate *priv;
714 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
716 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
717 G_CALLBACK (text_buffer_refresh_attributes), obj);
718 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
719 G_CALLBACK (text_buffer_can_undo), obj);
720 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
721 G_CALLBACK (text_buffer_can_redo), obj);
722 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
723 G_CALLBACK (body_changed), obj);
724 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
725 G_CALLBACK (body_insert_text), obj);
726 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
727 G_CALLBACK (body_changed), obj);
728 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
729 G_CALLBACK (text_buffer_end_user_action), obj);
730 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
731 G_CALLBACK (text_buffer_mark_set), obj);
732 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
733 G_CALLBACK (text_buffer_apply_tag), obj);
734 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
735 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
736 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
737 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
738 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
739 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
741 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
742 G_CALLBACK (from_field_changed), obj);
744 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
745 G_CALLBACK (msg_body_focus), obj);
746 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
747 G_CALLBACK (msg_body_focus), obj);
748 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
749 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
750 "changed", G_CALLBACK (recpt_field_changed), obj);
751 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
752 "changed", G_CALLBACK (recpt_field_changed), obj);
753 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
754 "changed", G_CALLBACK (recpt_field_changed), obj);
755 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
756 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
757 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
759 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
760 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
762 priv->clipboard_change_handler_id =
763 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
764 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
765 priv->default_clipboard_change_handler_id =
766 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
767 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
769 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
770 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
771 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
775 init_wp_text_view_style ()
777 static gboolean initialized = FALSE;
780 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
786 init_window (ModestMsgEditWindow *obj)
788 GtkWidget *to_caption, *subject_caption;
789 GtkWidget *main_vbox;
790 ModestMsgEditWindowPrivate *priv;
791 GtkActionGroup *action_group;
792 ModestWindowPrivate *parent_priv;
793 GdkPixbuf *window_icon = NULL;
794 GError *error = NULL;
796 GtkSizeGroup *title_size_group;
797 GtkSizeGroup *value_size_group;
798 GtkWidget *window_box;
799 GtkWidget *window_align;
800 #if (GTK_MINOR_VERSION >= 10)
801 GdkAtom deserialize_type;
803 GtkWidget *from_send_hbox;
804 GtkWidget *send_icon;
805 GtkWidget *attachments_label;
807 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
808 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
810 parent_priv->ui_manager = gtk_ui_manager_new();
811 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
812 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
814 /* Add common actions */
815 gtk_action_group_add_actions (action_group,
816 modest_msg_edit_action_entries,
817 G_N_ELEMENTS (modest_msg_edit_action_entries),
819 gtk_action_group_add_actions (action_group,
820 hildon2_msg_edit_action_entries,
821 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
823 gtk_action_group_add_toggle_actions (action_group,
824 modest_msg_edit_toggle_action_entries,
825 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
827 gtk_action_group_add_radio_actions (action_group,
828 modest_msg_edit_alignment_radio_action_entries,
829 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
831 G_CALLBACK (modest_ui_actions_on_change_justify),
833 gtk_action_group_add_radio_actions (action_group,
834 modest_msg_edit_priority_action_entries,
835 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
837 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
839 gtk_action_group_add_radio_actions (action_group,
840 modest_msg_edit_file_format_action_entries,
841 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
842 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
843 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
845 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
846 g_object_unref (action_group);
848 /* Load the UI definition */
849 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
852 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
853 g_clear_error (&error);
856 /* Add accelerators */
857 gtk_window_add_accel_group (GTK_WINDOW (obj),
858 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
860 parent_priv->menubar = NULL;
862 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
863 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
865 /* Note: This ModestPairList* must exist for as long as the picker
866 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
867 * so it can't know how to manage its memory. */
868 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
869 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
871 modest_selector_picker_set_value_max_chars (MODEST_SELECTOR_PICKER (priv->from_field), MAX_FROM_VALUE);
872 modest_maemo_utils_set_hbutton_layout (title_size_group, NULL,
873 _("mail_va_from"), priv->from_field);
874 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
875 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
876 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
878 priv->to_field = modest_recpt_editor_new ();
879 priv->cc_field = modest_recpt_editor_new ();
880 priv->bcc_field = modest_recpt_editor_new ();
881 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
882 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
883 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
884 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
885 priv->priority_icon = gtk_image_new ();
886 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
887 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
888 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
889 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
890 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
891 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
892 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
893 priv->attachments_view = modest_attachments_view_new (NULL);
894 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
895 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
897 priv->header_box = gtk_vbox_new (FALSE, 0);
899 to_caption = _create_addressbook_box
900 (title_size_group, value_size_group,
901 _("mail_va_to"), priv->to_field);
902 priv->cc_caption = _create_addressbook_box
903 (title_size_group, value_size_group,
904 _("mail_va_cc"), priv->cc_field);
905 priv->bcc_caption = _create_addressbook_box
906 (title_size_group, value_size_group,
907 _("mail_va_hotfix1"), priv->bcc_field);
908 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
909 _("mail_va_subject"), FALSE, priv->subject_box);
910 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (NULL, NULL,
911 _("mail_va_attachment"),
913 priv->attachments_view,
914 HILDON_SIZE_AUTO_WIDTH |
915 HILDON_SIZE_AUTO_HEIGHT);
916 attachments_label = modest_maemo_utils_captioned_get_label_widget (priv->attachments_caption);
917 hildon_gtk_widget_set_theme_size (attachments_label, HILDON_SIZE_AUTO_HEIGHT);
920 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
921 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
922 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
923 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 148, -1);
925 g_object_unref (title_size_group);
926 g_object_unref (value_size_group);
928 from_send_hbox = gtk_hbox_new (FALSE, 0);
929 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->from_field, TRUE, TRUE, 0);
930 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
932 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
933 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
934 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
935 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
936 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
937 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
938 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
940 init_wp_text_view_style ();
942 priv->msg_body = modest_wp_text_view_new ();
945 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
946 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
947 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
948 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
949 #if (GTK_MINOR_VERSION >= 10)
950 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
951 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
953 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
954 deserialize_type, TRUE);
956 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
958 priv->find_toolbar = hildon_find_toolbar_new (NULL);
959 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
961 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
963 priv->pannable = hildon_pannable_area_new ();
965 g_object_set (G_OBJECT (priv->pannable), "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
967 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
968 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
969 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
971 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
972 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
973 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
975 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
976 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
978 window_box = gtk_vbox_new (FALSE, 0);
979 gtk_container_add (GTK_CONTAINER(obj), window_box);
981 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
983 /* Set window icon */
984 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
986 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
987 g_object_unref (window_icon);
992 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
994 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
996 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
997 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
998 priv->clipboard_change_handler_id))
999 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1000 priv->clipboard_change_handler_id);
1001 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1002 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1003 priv->default_clipboard_change_handler_id))
1004 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1005 priv->default_clipboard_change_handler_id);
1007 if (priv->account_removed_handler_id &&
1008 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1009 priv->account_removed_handler_id))
1010 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1011 priv->account_removed_handler_id);
1015 modest_msg_edit_window_finalize (GObject *obj)
1017 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1019 /* Sanity check: shouldn't be needed, the window mgr should
1020 call this function before */
1021 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1023 if (priv->font_dialog != NULL) {
1024 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1027 if (priv->clipboard_text != NULL) {
1028 g_free (priv->clipboard_text);
1029 priv->clipboard_text = NULL;
1032 if (priv->draft_msg != NULL) {
1033 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1034 if (TNY_IS_HEADER (header)) {
1035 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1036 modest_window_mgr_unregister_header (mgr, header);
1038 g_object_unref (priv->draft_msg);
1039 priv->draft_msg = NULL;
1041 if (priv->outbox_msg != NULL) {
1042 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1043 if (TNY_IS_HEADER (header)) {
1044 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1045 modest_window_mgr_unregister_header (mgr, header);
1047 g_object_unref (priv->outbox_msg);
1048 priv->outbox_msg = NULL;
1050 if (priv->correct_scroll_idle > 0) {
1051 g_source_remove (priv->correct_scroll_idle);
1052 priv->correct_scroll_idle = 0;
1054 if (priv->scroll_drag_timeout_id > 0) {
1055 g_source_remove (priv->scroll_drag_timeout_id);
1056 priv->scroll_drag_timeout_id = 0;
1058 if (priv->clipboard_owner_idle > 0) {
1059 g_source_remove (priv->clipboard_owner_idle);
1060 priv->clipboard_owner_idle = 0;
1062 if (priv->original_account_name)
1063 g_free (priv->original_account_name);
1064 if (priv->original_mailbox)
1065 g_free (priv->original_mailbox);
1066 g_free (priv->msg_uid);
1067 g_free (priv->last_search);
1068 g_free (priv->references);
1069 g_free (priv->in_reply_to);
1070 g_object_unref (priv->faces_model);
1071 g_object_unref (priv->sizes_model);
1072 g_object_unref (priv->attachments);
1073 g_object_unref (priv->images);
1075 /* This had to stay alive for as long as the picker that used it: */
1076 modest_pair_list_free (priv->from_field_protos);
1078 G_OBJECT_CLASS(parent_class)->finalize (obj);
1082 pixbuf_size_prepared (GdkPixbufLoader *loader,
1085 ModestMsgEditWindow *self)
1087 gint new_height, new_width;
1090 new_height = height;
1094 if (width > IMAGE_MAX_WIDTH) {
1095 new_height = height * IMAGE_MAX_WIDTH / width;
1096 new_width = IMAGE_MAX_WIDTH;
1099 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1103 pixbuf_from_stream (TnyStream *stream,
1104 const gchar *mime_type,
1105 guint64 *stream_size,
1106 ModestMsgEditWindow *self)
1108 GdkPixbufLoader *loader;
1111 GError *error = NULL;
1115 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1117 if (loader == NULL) {
1122 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1124 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1126 tny_stream_reset (TNY_STREAM (stream));
1127 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1128 unsigned char read_buffer[128];
1130 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1132 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1135 /* Allow some UI responsiveness */
1136 while (gtk_events_pending ())
1137 gtk_main_iteration ();
1139 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1141 gdk_pixbuf_loader_close (loader, &error);
1144 g_error_free (error);
1145 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1147 g_object_ref (pixbuf);
1148 g_object_unref (loader);
1153 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1154 GdkPixbuf *new_pixbuf;
1156 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1157 gdk_pixbuf_get_width (pixbuf);
1158 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1159 g_object_unref (pixbuf);
1160 pixbuf = new_pixbuf;
1164 *stream_size = size;
1170 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1172 ModestMsgEditWindowPrivate *priv;
1175 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1177 g_object_ref (self);
1178 for (iter = tny_list_create_iterator (attachments);
1179 !tny_iterator_is_done (iter);
1180 tny_iterator_next (iter)) {
1181 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1182 const gchar *cid = tny_mime_part_get_content_id (part);
1183 const gchar *mime_type = tny_mime_part_get_content_type (part);
1184 if ((cid != NULL)&&(mime_type != NULL)) {
1185 guint64 stream_size;
1186 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1187 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1190 g_object_unref (stream);
1192 if (pixbuf != NULL) {
1193 priv->images_count ++;
1194 priv->images_size += stream_size;
1195 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1196 g_object_unref (pixbuf);
1199 g_object_unref (part);
1201 g_object_unref (iter);
1202 g_object_unref (self);
1206 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1208 TnyMimePart *parent = NULL;
1209 const gchar *content_type = NULL;
1210 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1212 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1214 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1215 parent = g_object_ref (msg);
1216 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1217 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1220 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1221 iter = tny_list_create_iterator (parts);
1222 while (!tny_iterator_is_done (iter)) {
1224 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1225 content_type = tny_mime_part_get_content_type (part);
1226 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1230 g_object_unref (part);
1232 tny_iterator_next (iter);
1234 g_object_unref (iter);
1235 g_object_unref (parts);
1238 if (parent != NULL) {
1239 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1242 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1243 iter = tny_list_create_iterator (parts);
1244 while (!tny_iterator_is_done (iter)) {
1246 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1247 content_type = tny_mime_part_get_content_type (part);
1248 if (content_type && g_str_has_prefix (content_type, "image/")) {
1249 tny_list_prepend (priv->images, (GObject *) part);
1251 g_object_unref (part);
1252 tny_iterator_next (iter);
1254 g_object_unref (iter);
1255 g_object_unref (parts);
1256 g_object_unref (parent);
1261 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1264 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1266 for (iter = tny_list_create_iterator (attachments) ;
1267 !tny_iterator_is_done (iter);
1268 tny_iterator_next (iter)) {
1269 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1270 const gchar *cid = tny_mime_part_get_content_id (part);
1272 char *invalid = NULL;
1273 gint int_cid = strtol (cid, &invalid, 10);
1274 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1275 priv->next_cid = int_cid + 1;
1278 g_object_unref (part);
1280 g_object_unref (iter);
1284 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1287 gchar *to, *cc, *bcc, *subject;
1289 ModestMsgEditWindowPrivate *priv;
1290 ModestWindowPrivate *parent_priv;
1292 TnyHeaderFlags priority_flags;
1293 TnyFolder *msg_folder;
1294 gboolean is_html = FALSE;
1295 gboolean field_view_set;
1297 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1298 g_return_if_fail (TNY_IS_MSG (msg));
1300 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1301 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1303 header = tny_msg_get_header (msg);
1304 to = tny_header_dup_to (header);
1305 cc = tny_header_dup_cc (header);
1306 bcc = tny_header_dup_bcc (header);
1307 subject = tny_header_dup_subject (header);
1309 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1310 priority_flags = tny_header_get_priority (header);
1313 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1315 field_view_set = TRUE;
1317 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1318 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1319 gtk_widget_show (priv->cc_caption);
1320 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1321 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1322 gtk_widget_hide (priv->cc_caption);
1323 field_view_set = FALSE;
1325 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1327 field_view_set = TRUE;
1329 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1330 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1331 gtk_widget_show (priv->bcc_caption);
1332 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1333 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1334 gtk_widget_hide (priv->bcc_caption);
1335 field_view_set = FALSE;
1337 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1341 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1342 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1345 update_window_title (self);
1347 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1348 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1350 if ((body == NULL)||(body[0] == '\0')) {
1352 body = modest_text_utils_convert_to_html ("");
1355 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1356 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1359 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1362 /* Add attachments to the view */
1363 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1364 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1365 if (tny_list_get_length (priv->attachments) == 0) {
1366 gtk_widget_hide (priv->attachments_caption);
1368 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1369 gtk_widget_show_all (priv->attachments_caption);
1371 get_related_images (self, msg);
1372 update_next_cid (self, priv->attachments);
1373 update_next_cid (self, priv->images);
1374 replace_with_images (self, priv->images);
1376 if (preserve_is_rich && !is_html) {
1377 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1378 /* Get the default format required from configuration */
1379 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1380 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1383 /* Set the default focus depending on having already a To: field or not */
1384 if ((!to)||(*to == '\0')) {
1385 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1387 gtk_widget_grab_focus (priv->msg_body);
1390 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1392 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1393 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1395 modest_msg_edit_window_set_modified (self, FALSE);
1397 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1398 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1399 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1400 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1402 if (priv->msg_uid) {
1403 g_free (priv->msg_uid);
1404 priv->msg_uid = NULL;
1407 /* we should set a reference to the incoming message if it is a draft */
1408 msg_folder = tny_msg_get_folder (msg);
1410 if (modest_tny_folder_is_local_folder (msg_folder)) {
1411 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1412 if (type == TNY_FOLDER_TYPE_INVALID)
1413 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1415 if (type == TNY_FOLDER_TYPE_DRAFTS)
1416 priv->draft_msg = g_object_ref(msg);
1417 if (type == TNY_FOLDER_TYPE_OUTBOX)
1418 priv->outbox_msg = g_object_ref(msg);
1419 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1421 g_object_unref (msg_folder);
1432 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1434 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1435 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1436 GtkWidget *placeholder;
1437 GtkWidget *tool_item;
1442 GtkWidget *sizes_menu;
1443 GtkWidget *fonts_menu;
1449 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1450 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1451 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1452 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1454 /* Font color placeholder */
1455 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1456 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1459 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1460 priv->font_color_button = hildon_color_button_new ();
1461 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1462 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1463 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1464 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1465 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1466 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1467 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1468 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1470 G_CALLBACK (modest_msg_edit_window_color_button_change),
1473 /* Font size and face placeholder */
1474 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1475 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1477 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1478 priv->size_tool_button_label = gtk_label_new (NULL);
1479 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1480 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1481 size_text, "</span>", NULL);
1482 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1483 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1485 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1486 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1487 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1488 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1489 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1490 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1491 gtk_widget_set_sensitive (arrow, FALSE);
1492 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1493 sizes_menu = gtk_menu_new ();
1494 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1495 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1498 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1499 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1501 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1505 if (wp_font_size[size_index] == 12)
1506 priv->current_size_index = size_index;
1510 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1511 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1512 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1513 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1514 priv->font_size_toolitem = tool_item;
1517 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1518 priv->font_tool_button_label = gtk_label_new (NULL);
1519 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1520 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1521 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1523 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1524 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1525 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1526 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1527 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1528 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1529 gtk_widget_set_sensitive (arrow, FALSE);
1530 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1531 fonts_menu = gtk_menu_new ();
1532 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1533 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1536 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1538 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1539 0, wp_get_font_name (font_index),
1542 if (font_index == DEFAULT_FONT)
1543 priv->current_face_index = font_index;
1545 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1546 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1547 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1548 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1549 priv->font_face_toolitem = tool_item;
1551 /* Set expand and homogeneous for remaining items */
1552 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1553 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1554 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1555 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1556 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1557 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1559 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1560 will not show the tool items added to the placeholders) */
1561 gtk_widget_show_all (parent_priv->toolbar);
1563 /* Set the no show all *after* showing all items. We do not
1564 want the toolbar to be shown with a show all because it
1565 could go agains the gconf setting regarding showing or not
1566 the toolbar of the editor window */
1567 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1573 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1576 ModestWindowPrivate *parent_priv;
1577 ModestMsgEditWindowPrivate *priv;
1578 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1579 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1580 ModestWindowMgr *mgr = NULL;
1582 g_return_val_if_fail (msg, NULL);
1583 g_return_val_if_fail (account_name, NULL);
1585 mgr = modest_runtime_get_window_mgr ();
1587 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1589 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1590 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1592 /* Menubar. Update the state of some toggles */
1593 priv->from_field_protos = get_transports ();
1594 priv->original_mailbox = NULL;
1595 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1596 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1597 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1598 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1599 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1600 priv->original_mailbox = g_strdup (mailbox);
1601 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1602 /* We set the first mailbox as the active mailbox */
1603 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1604 if (priv->original_mailbox != NULL)
1605 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1606 (gpointer) priv->original_mailbox);
1608 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1609 (gpointer) account_name);
1611 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1613 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1614 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1616 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1617 hildon_touch_selector_get_current_text
1618 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1619 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1620 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1623 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1625 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1627 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1628 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1630 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1632 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1633 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1634 /* Add common dimming rules */
1635 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1636 modest_msg_edit_window_toolbar_dimming_entries,
1637 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1638 MODEST_WINDOW (obj));
1639 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1640 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1641 MODEST_WINDOW (obj));
1642 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1643 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1644 MODEST_WINDOW (obj));
1645 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1646 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1647 MODEST_WINDOW (obj));
1648 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1649 G_CALLBACK (modest_ui_dimming_rules_on_send),
1650 MODEST_WINDOW (obj));
1651 /* Insert dimming rules group for this window */
1652 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1653 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1655 /* Setup app menu */
1656 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1658 /* Checks the dimming rules */
1659 g_object_unref (toolbar_rules_group);
1660 g_object_unref (clipboard_rules_group);
1661 gtk_widget_hide (priv->priority_icon);
1662 gtk_widget_queue_resize (priv->subject_box);
1663 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1665 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1667 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1668 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1669 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1670 priv->update_caption_visibility = TRUE;
1672 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1674 /* Track account-removed signal, this window should be closed
1675 in the case we're creating a mail associated to the account
1677 priv->account_removed_handler_id =
1678 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1680 G_CALLBACK(on_account_removed),
1683 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1685 return (ModestWindow*) obj;
1689 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1691 GString **string_buffer = (GString **) user_data;
1693 *string_buffer = g_string_append (*string_buffer, buffer);
1699 * @result: A new string which should be freed with g_free().
1702 get_formatted_data (ModestMsgEditWindow *edit_window)
1704 ModestMsgEditWindowPrivate *priv;
1705 GString *string_buffer = g_string_new ("");
1707 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1709 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1711 modest_text_utils_hyperlinkify (string_buffer);
1713 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1715 return g_string_free (string_buffer, FALSE);
1720 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1723 const gchar *account_name;
1724 ModestMsgEditWindowPrivate *priv;
1725 TnyIterator *att_iter;
1726 const gchar *picker_active_id;
1728 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1730 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1732 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1733 g_return_val_if_fail (picker_active_id, NULL);
1734 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1736 /* don't free these (except from) */
1737 data = g_slice_new0 (MsgData);
1738 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1739 data->account_name = g_strdup (account_name);
1740 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1741 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1742 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1743 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1744 data->references = g_strdup (priv->references);
1745 data->in_reply_to = g_strdup (priv->in_reply_to);
1746 if (priv->draft_msg) {
1747 data->draft_msg = g_object_ref (priv->draft_msg);
1748 } else if (priv->outbox_msg) {
1749 data->draft_msg = g_object_ref (priv->outbox_msg);
1751 data->draft_msg = NULL;
1754 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1756 gtk_text_buffer_get_bounds (buf, &b, &e);
1757 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1759 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1760 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1762 data->html_body = NULL;
1764 /* deep-copy the data */
1765 att_iter = tny_list_create_iterator (priv->attachments);
1766 data->attachments = NULL;
1767 while (!tny_iterator_is_done (att_iter)) {
1768 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1769 if (!(TNY_IS_MIME_PART(part))) {
1770 g_warning ("strange data in attachment list");
1771 g_object_unref (part);
1772 tny_iterator_next (att_iter);
1775 data->attachments = g_list_append (data->attachments,
1777 tny_iterator_next (att_iter);
1779 g_object_unref (att_iter);
1781 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1782 att_iter = tny_list_create_iterator (priv->images);
1783 data->images = NULL;
1784 while (!tny_iterator_is_done (att_iter)) {
1785 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1787 if (!(TNY_IS_MIME_PART(part))) {
1788 g_warning ("strange data in attachment list");
1789 g_object_unref (part);
1790 tny_iterator_next (att_iter);
1793 cid = tny_mime_part_get_content_id (part);
1795 gchar *image_tag_id;
1796 GtkTextTag *image_tag;
1798 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1799 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1800 g_free (image_tag_id);
1802 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1804 ((gtk_text_iter_has_tag (&iter, image_tag))||
1805 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1806 data->images = g_list_append (data->images,
1807 g_object_ref (part));
1809 g_object_unref (part);
1810 tny_iterator_next (att_iter);
1812 g_object_unref (att_iter);
1814 data->priority_flags = priv->priority_flags;
1821 unref_gobject (GObject *obj, gpointer data)
1823 if (!G_IS_OBJECT(obj))
1825 g_object_unref (obj);
1829 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1832 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1840 g_free (data->from);
1841 g_free (data->subject);
1842 g_free (data->plain_body);
1843 g_free (data->html_body);
1844 g_free (data->account_name);
1845 g_free (data->references);
1846 g_free (data->in_reply_to);
1848 if (data->draft_msg != NULL) {
1849 g_object_unref (data->draft_msg);
1850 data->draft_msg = NULL;
1853 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1854 g_list_free (data->attachments);
1855 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1856 g_list_free (data->images);
1858 g_slice_free (MsgData, data);
1862 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1864 guint64 *parts_size)
1866 ModestMsgEditWindowPrivate *priv;
1868 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1870 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1872 /* TODO: add images */
1873 *parts_size += priv->images_size;
1874 *parts_count += priv->images_count;
1879 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1882 ModestMsgEditWindowPrivate *priv = NULL;
1883 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1885 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1887 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1889 return MODEST_MSG_EDIT_FORMAT_HTML;
1891 return MODEST_MSG_EDIT_FORMAT_TEXT;
1895 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1896 ModestMsgEditFormat format)
1898 ModestMsgEditWindowPrivate *priv;
1899 ModestWindowPrivate *parent_priv;
1901 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1902 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1903 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1906 case MODEST_MSG_EDIT_FORMAT_HTML:
1907 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1908 if (parent_priv->toolbar) gtk_widget_show (parent_priv->toolbar);
1910 case MODEST_MSG_EDIT_FORMAT_TEXT:
1911 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1912 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
1915 g_return_if_reached ();
1919 ModestMsgEditFormatState *
1920 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1922 ModestMsgEditFormatState *format_state = NULL;
1923 ModestMsgEditWindowPrivate *priv;
1924 WPTextBufferFormat *buffer_format;
1926 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1928 buffer_format = g_new0 (WPTextBufferFormat, 1);
1929 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1931 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1933 format_state = g_new0 (ModestMsgEditFormatState, 1);
1934 format_state->bold = buffer_format->bold&0x1;
1935 format_state->italics = buffer_format->italic&0x1;
1936 format_state->bullet = buffer_format->bullet&0x1;
1937 format_state->color = buffer_format->color;
1938 format_state->font_size = buffer_format->font_size;
1939 format_state->font_family = wp_get_font_name (buffer_format->font);
1940 format_state->justification = buffer_format->justification;
1941 g_free (buffer_format);
1943 return format_state;
1948 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1949 const ModestMsgEditFormatState *format_state)
1951 ModestMsgEditWindowPrivate *priv;
1952 WPTextBufferFormat *buffer_format;
1953 WPTextBufferFormat *current_format;
1955 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1956 g_return_if_fail (format_state != NULL);
1958 buffer_format = g_new0 (WPTextBufferFormat, 1);
1959 current_format = g_new0 (WPTextBufferFormat, 1);
1961 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1962 gtk_widget_grab_focus (priv->msg_body);
1963 buffer_format->bold = (format_state->bold != FALSE);
1964 buffer_format->italic = (format_state->italics != FALSE);
1965 buffer_format->color = format_state->color;
1966 buffer_format->font_size = format_state->font_size;
1967 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1968 buffer_format->justification = format_state->justification;
1969 buffer_format->bullet = format_state->bullet;
1971 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1973 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1974 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1975 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1976 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1977 buffer_format->cs.font = (buffer_format->font != current_format->font);
1978 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1979 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1981 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1982 if (buffer_format->cs.bold) {
1983 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1984 GINT_TO_POINTER (buffer_format->bold&0x1));
1986 if (buffer_format->cs.italic) {
1987 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1988 GINT_TO_POINTER (buffer_format->italic&0x1));
1990 if (buffer_format->cs.color) {
1991 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1992 GINT_TO_POINTER (&(buffer_format->color)));
1994 if (buffer_format->cs.font_size) {
1995 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1996 GINT_TO_POINTER (buffer_format->font_size));
1998 if (buffer_format->cs.justification) {
1999 switch (buffer_format->justification) {
2000 case GTK_JUSTIFY_LEFT:
2001 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2002 GINT_TO_POINTER(TRUE));
2004 case GTK_JUSTIFY_CENTER:
2005 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2006 GINT_TO_POINTER(TRUE));
2008 case GTK_JUSTIFY_RIGHT:
2009 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2010 GINT_TO_POINTER(TRUE));
2017 if (buffer_format->cs.font) {
2018 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2019 GINT_TO_POINTER (buffer_format->font));
2021 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2022 if (buffer_format->cs.bullet) {
2023 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2024 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2026 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2028 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2030 g_free (buffer_format);
2031 g_free (current_format);
2033 /* Check dimming rules */
2034 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2035 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2039 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2041 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2043 ModestWindowPrivate *parent_priv;
2044 ModestMsgEditWindowPrivate *priv;
2046 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2047 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2049 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2050 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2051 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2052 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2054 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2055 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2056 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2059 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2061 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2062 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2064 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2065 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2067 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2068 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2071 switch (buffer_format->justification)
2073 case GTK_JUSTIFY_LEFT:
2074 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2076 case GTK_JUSTIFY_CENTER:
2077 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2079 case GTK_JUSTIFY_RIGHT:
2080 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2087 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2089 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2090 G_CALLBACK (modest_msg_edit_window_color_button_change),
2092 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2093 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2094 G_CALLBACK (modest_msg_edit_window_color_button_change),
2097 if (priv->current_size_index != buffer_format->font_size) {
2101 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2102 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2106 priv->current_size_index = buffer_format->font_size;
2108 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2109 markup = g_strconcat ("<span font_family='Sans'>",
2110 size_text, "</span>", NULL);
2112 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2116 gtk_tree_path_free (path);
2119 if (priv->current_face_index != buffer_format->font) {
2123 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2124 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2128 priv->current_face_index = buffer_format->font;
2129 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2130 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2131 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2138 g_free (buffer_format);
2142 #ifdef MODEST_HILDON_VERSION_0
2144 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2147 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2148 ModestMsgEditWindowPrivate *priv;
2149 GtkWidget *dialog = NULL;
2151 GdkColor *new_color = NULL;
2153 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2154 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2156 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2157 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2158 g_free (buffer_format);
2160 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2161 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2162 if (new_color != NULL) {
2163 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2164 (gpointer) new_color);
2167 gtk_widget_destroy (dialog);
2172 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2175 ModestMsgEditWindowPrivate *priv;
2176 GtkWidget *dialog = NULL;
2178 GdkColor *old_color = NULL;
2179 const GdkColor *new_color = NULL;
2181 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2182 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2184 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2185 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2187 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2188 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2189 if (new_color != NULL)
2190 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2192 gtk_widget_destroy (dialog);
2198 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2201 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2202 ModestMsgEditWindowPrivate *priv;
2203 GtkWidget *dialog = NULL;
2205 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2206 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2208 dialog = hildon_color_chooser_new ();
2209 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2210 g_free (buffer_format);
2212 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2214 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2215 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2218 gtk_widget_destroy (dialog);
2223 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2226 ModestMsgEditWindowPrivate *priv;
2227 GtkWidget *dialog = NULL;
2228 GdkColor *old_color = NULL;
2230 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2231 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2233 dialog = hildon_color_chooser_new ();
2234 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2236 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2238 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2239 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2241 gtk_widget_destroy (dialog);
2244 #endif /*!MODEST_HILDON_VERSION_0*/
2249 create_stream_for_uri (const gchar* uri)
2254 TnyStream *result = NULL;
2256 GnomeVFSHandle *handle = NULL;
2257 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2258 if (test == GNOME_VFS_OK) {
2259 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2260 /* Streams over OBEX (Bluetooth) are not seekable but
2261 * we expect them to be (we might need to read them
2262 * several times). So if this is a Bluetooth URI just
2263 * read the whole file into memory (this is not a fast
2264 * protocol so we can assume that these files are not
2265 * going to be very big) */
2266 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2267 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2268 TnyStream *memstream = tny_camel_mem_stream_new ();
2269 tny_stream_write_to_stream (vfssstream, memstream);
2270 g_object_unref (vfssstream);
2273 result = vfssstream;
2281 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2284 ModestMsgEditWindowPrivate *priv;
2285 GtkWidget *dialog = NULL;
2287 GSList *uris = NULL;
2288 GSList *uri_node = NULL;
2290 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2292 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2293 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2294 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2296 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2298 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2299 GTK_WINDOW (dialog), GTK_WINDOW (window));
2301 response = gtk_dialog_run (GTK_DIALOG (dialog));
2303 case GTK_RESPONSE_OK:
2305 gchar *current_folder;
2306 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2307 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2308 if (current_folder && current_folder != '\0') {
2310 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2311 current_folder, &err);
2313 g_debug ("Error storing latest used folder: %s", err->message);
2317 g_free (current_folder);
2323 gtk_widget_destroy (dialog);
2325 g_object_ref (window);
2326 /* The operation could take some time so allow the dialog to be closed */
2327 while (gtk_events_pending ())
2328 gtk_main_iteration ();
2330 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2332 GnomeVFSHandle *handle = NULL;
2333 GnomeVFSResult result;
2334 GtkTextIter position;
2335 GtkTextMark *insert_mark;
2337 uri = (const gchar *) uri_node->data;
2338 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2339 if (result == GNOME_VFS_OK) {
2341 GnomeVFSFileInfo *info;
2342 gchar *filename, *basename, *escaped_filename;
2343 TnyMimePart *mime_part;
2345 const gchar *mime_type = NULL;
2346 GnomeVFSURI *vfs_uri;
2347 guint64 stream_size;
2349 gnome_vfs_close (handle);
2350 vfs_uri = gnome_vfs_uri_new (uri);
2352 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2353 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2354 g_free (escaped_filename);
2355 gnome_vfs_uri_unref (vfs_uri);
2356 info = gnome_vfs_file_info_new ();
2358 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2359 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2361 mime_type = gnome_vfs_file_info_get_mime_type (info);
2363 mime_part = tny_platform_factory_new_mime_part
2364 (modest_runtime_get_platform_factory ());
2366 TnyStream *stream = create_stream_for_uri (uri);
2368 if (stream == NULL) {
2370 modest_platform_information_banner (NULL, NULL,
2371 _FM("sfil_ib_opening_not_allowed"));
2373 g_object_unref (mime_part);
2374 gnome_vfs_file_info_unref (info);
2378 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2380 content_id = g_strdup_printf ("%d", priv->next_cid);
2381 tny_mime_part_set_content_id (mime_part, content_id);
2382 g_free (content_id);
2385 basename = g_path_get_basename (filename);
2386 tny_mime_part_set_filename (mime_part, basename);
2389 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2391 if (pixbuf != NULL) {
2392 priv->images_size += stream_size;
2393 priv->images_count ++;
2394 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2395 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2396 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2397 tny_mime_part_get_content_id (mime_part), pixbuf);
2398 g_object_unref (pixbuf);
2400 tny_list_prepend (priv->images, (GObject *) mime_part);
2401 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2403 modest_platform_information_banner (NULL, NULL,
2404 _("mail_ib_file_operation_failed"));
2408 g_object_unref (mime_part);
2409 gnome_vfs_file_info_unref (info);
2413 g_object_unref (window);
2417 on_attach_file_response (GtkDialog *dialog,
2421 GSList *uris = NULL;
2423 GnomeVFSFileSize total_size, allowed_size;
2424 ModestMsgEditWindow *window;
2425 ModestMsgEditWindowPrivate *priv;
2430 case GTK_RESPONSE_OK:
2432 gchar *current_folder;
2434 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2435 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2436 if (current_folder && current_folder != '\0') {
2438 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2439 current_folder, &err);
2441 g_debug ("Error storing latest used folder: %s", err->message);
2445 g_free (current_folder);
2452 window = MODEST_MSG_EDIT_WINDOW (user_data);
2453 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2455 /* allowed size is the maximum size - what's already there */
2456 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2457 &att_num, &att_size);
2458 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2461 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2463 const gchar *uri = (const gchar *) uri_node->data;
2466 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2468 if (total_size > allowed_size) {
2469 g_warning ("%s: total size: %u",
2470 __FUNCTION__, (unsigned int)total_size);
2473 allowed_size -= total_size;
2475 g_slist_foreach (uris, (GFunc) g_free, NULL);
2476 g_slist_free (uris);
2478 gtk_widget_destroy (GTK_WIDGET (dialog));
2482 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2484 GtkWidget *dialog = NULL;
2485 ModestMsgEditWindowPrivate *priv;
2488 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2490 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2492 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2495 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2496 GTK_FILE_CHOOSER_ACTION_OPEN);
2497 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2498 conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2499 if (conf_folder && conf_folder[0] != '\0') {
2500 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2503 /* Set the default folder to images folder */
2504 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2505 ".documents", NULL);
2506 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2507 g_free (docs_folder);
2509 g_free (conf_folder);
2510 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2511 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2512 GTK_WINDOW (dialog), GTK_WINDOW (window));
2514 /* Connect to response & show */
2515 g_signal_connect (dialog, "response",
2516 G_CALLBACK (on_attach_file_response), window);
2517 gtk_widget_show (dialog);
2522 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2524 GnomeVFSFileSize allowed_size)
2527 GnomeVFSHandle *handle = NULL;
2528 ModestMsgEditWindowPrivate *priv;
2529 GnomeVFSResult result;
2530 GnomeVFSFileSize size = 0;
2531 g_return_val_if_fail (window, 0);
2532 g_return_val_if_fail (uri, 0);
2534 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2536 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2537 if (result == GNOME_VFS_OK) {
2538 TnyMimePart *mime_part;
2540 const gchar *mime_type = NULL;
2542 gchar *escaped_filename;
2545 GnomeVFSFileInfo *info;
2546 GnomeVFSURI *vfs_uri;
2548 gnome_vfs_close (handle);
2549 vfs_uri = gnome_vfs_uri_new (uri);
2552 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2553 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2554 g_free (escaped_filename);
2555 gnome_vfs_uri_unref (vfs_uri);
2557 info = gnome_vfs_file_info_new ();
2559 if (gnome_vfs_get_file_info (uri,
2561 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2563 mime_type = gnome_vfs_file_info_get_mime_type (info);
2564 mime_part = tny_platform_factory_new_mime_part
2565 (modest_runtime_get_platform_factory ());
2567 /* try to get the attachment's size; this may fail for weird
2568 * file systems, like obex, upnp... */
2569 if (allowed_size != 0 &&
2570 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2572 if (size > allowed_size) {
2573 modest_platform_information_banner (NULL, NULL,
2574 _FM("sfil_ib_opening_not_allowed"));
2579 g_warning ("%s: could not get attachment size", __FUNCTION__);
2581 stream = create_stream_for_uri (uri);
2583 if (stream == NULL) {
2585 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2587 g_object_unref (mime_part);
2589 gnome_vfs_file_info_unref (info);
2593 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2594 g_object_unref (stream);
2596 content_id = g_strdup_printf ("%d", priv->next_cid);
2597 tny_mime_part_set_content_id (mime_part, content_id);
2598 g_free (content_id);
2601 basename = g_path_get_basename (filename);
2602 tny_mime_part_set_filename (mime_part, basename);
2605 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2606 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2608 info->size == 0, info->size);
2609 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2610 gtk_widget_show_all (priv->attachments_caption);
2611 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2613 g_object_unref (mime_part);
2614 gnome_vfs_file_info_unref (info);
2621 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2624 ModestMsgEditWindowPrivate *priv;
2627 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2628 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2630 if (att_list == NULL) {
2631 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2632 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2633 g_object_unref (att_list);
2638 g_object_ref (att_list);
2641 if (tny_list_get_length (att_list) == 0) {
2642 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2644 gboolean dialog_response;
2645 gchar *message = NULL;
2646 gchar *filename = NULL;
2648 if (tny_list_get_length (att_list) == 1) {
2650 iter = tny_list_create_iterator (att_list);
2651 part = (TnyMimePart *) tny_iterator_get_current (iter);
2652 g_object_unref (iter);
2653 if (TNY_IS_MSG (part)) {
2654 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2656 filename = tny_header_dup_subject (header);
2657 g_object_unref (header);
2659 if (filename == NULL) {
2660 filename = g_strdup (_("mail_va_no_subject"));
2663 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2665 g_object_unref (part);
2667 filename = g_strdup ("");
2669 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2670 "emev_nc_delete_attachments",
2671 tny_list_get_length (att_list)), filename);
2674 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2678 if (dialog_response != GTK_RESPONSE_OK) {
2679 g_object_unref (att_list);
2683 for (iter = tny_list_create_iterator (att_list);
2684 !tny_iterator_is_done (iter);
2685 tny_iterator_next (iter)) {
2686 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2687 const gchar *att_id;
2688 tny_list_remove (priv->attachments, (GObject *) mime_part);
2690 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2692 if (tny_list_get_length (priv->attachments) == 0)
2693 gtk_widget_hide (priv->attachments_caption);
2694 att_id = tny_mime_part_get_content_id (mime_part);
2696 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2698 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2699 g_object_unref (mime_part);
2701 g_object_unref (iter);
2704 g_object_unref (att_list);
2706 /* if the last attachment has been removed, focus the Subject: field */
2707 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2708 gtk_widget_grab_focus (priv->subject_field);
2712 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2715 ModestMsgEditWindowPrivate *priv;
2716 GdkColor *new_color;
2717 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2719 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2720 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2723 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2725 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2727 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2729 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2734 font_size_clicked (GtkToolButton *button,
2735 ModestMsgEditWindow *window)
2737 ModestMsgEditWindowPrivate *priv;
2738 GtkWidget *selector, *dialog;
2740 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2742 selector = hildon_touch_selector_new ();
2743 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2744 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2746 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2747 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2748 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2750 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2754 WPTextBufferFormat format;
2756 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2758 memset (&format, 0, sizeof (format));
2759 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2761 format.cs.font_size = TRUE;
2762 format.cs.text_position = TRUE;
2763 format.cs.font = TRUE;
2764 format.font_size = new_index;
2765 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2767 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2768 GINT_TO_POINTER (new_index)))
2769 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2771 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2772 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2773 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2774 size_text, "</span>", NULL);
2776 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2780 gtk_widget_destroy (dialog);
2782 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2787 font_face_clicked (GtkToolButton *button,
2788 ModestMsgEditWindow *window)
2790 ModestMsgEditWindowPrivate *priv;
2791 GtkWidget *selector, *dialog;
2792 GtkCellRenderer *renderer;
2794 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2796 selector = hildon_touch_selector_new ();
2797 renderer = gtk_cell_renderer_text_new ();
2798 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2799 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2800 renderer, "family", 0, "text", 0, NULL);
2801 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2803 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2804 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2805 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2807 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2808 gint new_font_index;
2812 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2813 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2814 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2818 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2820 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2821 GINT_TO_POINTER(new_font_index)))
2822 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2824 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2825 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2827 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2831 gtk_tree_path_free (path);
2834 gtk_widget_destroy (dialog);
2836 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2841 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2844 ModestMsgEditWindowPrivate *priv = NULL;
2845 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2847 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2848 if (!priv->update_caption_visibility)
2851 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2853 gtk_widget_show (priv->cc_caption);
2855 gtk_widget_hide (priv->cc_caption);
2857 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2861 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2864 ModestMsgEditWindowPrivate *priv = NULL;
2865 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2867 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2868 if (!priv->update_caption_visibility)
2871 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2873 gtk_widget_show (priv->bcc_caption);
2875 gtk_widget_hide (priv->bcc_caption);
2877 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2881 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2882 ModestRecptEditor *editor)
2884 ModestMsgEditWindowPrivate *priv;
2886 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2887 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2889 /* we check for low-mem; in that case, show a warning, and don't allow
2890 * for the addressbook
2892 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2895 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2897 if (editor == NULL) {
2898 GtkWidget *view_focus;
2899 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2901 /* This code should be kept in sync with ModestRecptEditor. The
2902 textview inside the recpt editor is the one that really gets the
2903 focus. As it's inside a scrolled window, and this one inside the
2904 hbox recpt editor inherits from, we'll need to go up in the
2905 hierarchy to know if the text view is part of the recpt editor
2906 or if it's a different text entry */
2908 if (gtk_widget_get_parent (view_focus)) {
2909 GtkWidget *first_parent;
2911 first_parent = gtk_widget_get_parent (view_focus);
2912 if (gtk_widget_get_parent (first_parent) &&
2913 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2914 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2919 editor = MODEST_RECPT_EDITOR (priv->to_field);
2923 modest_address_book_select_addresses (editor);
2928 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2930 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2932 modest_msg_edit_window_open_addressbook (window, NULL);
2936 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2937 gboolean show_toolbar)
2939 ModestWindowPrivate *parent_priv;
2940 ModestMsgEditWindowPrivate *priv;
2942 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2943 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2944 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2946 /* We can not just use the code of
2947 modest_msg_edit_window_setup_toolbar because it has a
2948 mixture of both initialization and creation code. */
2950 gint current_format;
2951 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2952 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2953 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
2954 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2956 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2959 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2964 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2965 TnyHeaderFlags priority_flags)
2967 ModestMsgEditWindowPrivate *priv;
2968 ModestWindowPrivate *parent_priv;
2970 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2972 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2973 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2975 if (priv->priority_flags != priority_flags) {
2976 GtkAction *priority_action = NULL;
2978 priv->priority_flags = priority_flags;
2980 switch (priority_flags) {
2981 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2982 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2983 MODEST_HEADER_ICON_HIGH,
2984 HILDON_ICON_SIZE_SMALL);
2985 gtk_widget_show (priv->priority_icon);
2986 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2987 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2989 case TNY_HEADER_FLAG_LOW_PRIORITY:
2990 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2991 MODEST_HEADER_ICON_LOW,
2992 HILDON_ICON_SIZE_SMALL);
2993 gtk_widget_show (priv->priority_icon);
2994 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2995 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2998 gtk_widget_hide (priv->priority_icon);
2999 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3000 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3003 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3004 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3006 gtk_widget_queue_resize (priv->subject_box);
3010 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3013 ModestMsgEditWindowPrivate *priv;
3014 ModestWindowPrivate *parent_priv;
3015 gint current_format;
3017 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3019 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3020 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3022 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3023 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3025 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3027 if (parent_priv->toolbar) {
3028 if (file_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3029 gtk_widget_hide (parent_priv->toolbar);
3031 gtk_widget_show (parent_priv->toolbar);
3035 if (current_format != file_format) {
3036 switch (file_format) {
3037 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3038 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3039 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3041 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3045 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3046 response = gtk_dialog_run (GTK_DIALOG (dialog));
3047 gtk_widget_destroy (dialog);
3048 if (response == GTK_RESPONSE_OK) {
3049 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3050 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
3052 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3053 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3058 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3059 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3060 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3065 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3068 ModestMsgEditWindowPrivate *priv;
3069 WPTextBufferFormat oldfmt, fmt;
3070 gint old_position = 0;
3074 GdkColor *color = NULL;
3075 gboolean bold, bold_set, italic, italic_set;
3076 gboolean underline, underline_set;
3077 gboolean strikethrough, strikethrough_set;
3078 gboolean position_set;
3079 gboolean font_size_set, font_set, color_set;
3082 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3083 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3085 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3086 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3087 GTK_WINDOW(dialog), GTK_WINDOW (window));
3089 /* First we get the currently selected font information */
3090 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3092 switch (oldfmt.text_position) {
3093 case TEXT_POSITION_NORMAL:
3096 case TEXT_POSITION_SUPERSCRIPT: