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
96 static gboolean is_wp_text_buffer_started = FALSE;
98 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
99 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
100 static void modest_msg_edit_window_finalize (GObject *obj);
102 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
103 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
104 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
106 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
107 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
108 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
109 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
110 GtkTextIter *start, GtkTextIter *end,
112 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
113 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
114 static void subject_field_insert_text (GtkEditable *editable,
116 gint new_text_length,
118 ModestMsgEditWindow *window);
119 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
121 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
123 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
124 ModestRecptEditor *editor);
125 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
126 ModestMsgEditWindow *window);
128 /* ModestWindow methods implementation */
129 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
130 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
131 gboolean show_toolbar);
132 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
134 ModestMsgEditWindow *window);
135 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
136 static void subject_field_move_cursor (GtkEntry *entry,
137 GtkMovementStep step,
141 static void update_window_title (ModestMsgEditWindow *window);
144 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
145 ModestMsgEditWindow *window);
146 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
147 ModestMsgEditWindow *window);
148 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
150 GtkTextIter *match_start,
151 GtkTextIter *match_end);
153 static void remove_tags (WPTextBuffer *buffer);
155 static void on_account_removed (TnyAccountStore *account_store,
159 static void init_window (ModestMsgEditWindow *obj);
161 gboolean scroll_drag_timeout (gpointer userdata);
162 static void correct_scroll (ModestMsgEditWindow *w);
163 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
164 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
165 ModestMsgEditWindow *userdata);
166 static void text_buffer_mark_set (GtkTextBuffer *buffer,
169 ModestMsgEditWindow *userdata);
170 static void on_message_settings (GtkAction *action,
171 ModestMsgEditWindow *window);
172 static void setup_menu (ModestMsgEditWindow *self);
174 static void from_field_changed (HildonPickerButton *button,
175 ModestMsgEditWindow *self);
176 static void font_size_clicked (GtkToolButton *button,
177 ModestMsgEditWindow *window);
178 static void font_face_clicked (GtkToolButton *button,
179 ModestMsgEditWindow *window);
180 static void update_signature (ModestMsgEditWindow *self,
181 const gchar *old_account,
182 const gchar *new_account);
183 static void DEBUG_BUFFER (WPTextBuffer *buffer)
187 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
189 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
190 while (!gtk_text_iter_is_end (&iter)) {
191 GString *output = g_string_new ("");
192 GSList *toggled_tags;
195 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
196 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
197 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
198 GtkTextTag *tag = (GtkTextTag *) node->data;
200 g_object_get (G_OBJECT (tag), "name", &name, NULL);
201 output = g_string_append (output, name);
202 g_string_append (output, " ");
204 output = g_string_append (output, "] OPENED [ ");
205 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
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, "]\n");
214 g_message ("%s", output->str);
215 g_string_free (output, TRUE);
216 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
218 g_message ("END BUFFER");
222 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
223 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
227 /* static gboolean */
228 /* on_key_pressed (GtkWidget *self, */
229 /* GdkEventKey *event, */
230 /* gpointer user_data); */
232 /* list my signals */
239 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
240 struct _ModestMsgEditWindowPrivate {
242 GtkWidget *header_box;
244 ModestPairList *from_field_protos;
245 GtkWidget *from_field;
246 gchar *last_from_account;
247 gchar *original_account_name;
252 gchar *original_mailbox;
256 GtkWidget *bcc_field;
257 GtkWidget *subject_field;
258 GtkWidget *attachments_view;
259 GtkWidget *priority_icon;
260 GtkWidget *subject_box;
261 GtkWidget *add_attachment_button;
263 GtkWidget *cc_caption;
264 GtkWidget *bcc_caption;
265 gboolean update_caption_visibility;
266 GtkWidget *attachments_caption;
268 GtkTextBuffer *text_buffer;
270 GtkWidget *font_size_toolitem;
271 GtkWidget *font_face_toolitem;
272 GtkWidget *font_color_button;
273 GtkWidget *font_color_toolitem;
274 GSList *font_items_group;
275 GtkTreeModel *faces_model;
276 gint current_face_index;
277 GtkWidget *font_tool_button_label;
278 GtkTreeModel *sizes_model;
279 gint current_size_index;
280 GtkWidget *size_tool_button_label;
282 GtkWidget *find_toolbar;
285 GtkWidget *font_dialog;
288 guint correct_scroll_idle;
289 guint scroll_drag_timeout_id;
293 TnyList *attachments;
298 TnyHeaderFlags priority_flags;
300 gboolean can_undo, can_redo;
301 gulong clipboard_change_handler_id;
302 gulong default_clipboard_change_handler_id;
303 gulong account_removed_handler_id;
304 guint clipboard_owner_idle;
305 gchar *clipboard_text;
314 GtkWidget *cc_button;
315 GtkWidget *bcc_button;
318 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
319 MODEST_TYPE_MSG_EDIT_WINDOW, \
320 ModestMsgEditWindowPrivate))
322 static GtkWindowClass *parent_class = NULL;
324 /* uncomment the following if you have defined any signals */
325 /* static guint signals[LAST_SIGNAL] = {0}; */
328 modest_msg_edit_window_get_type (void)
330 static GType my_type = 0;
332 static const GTypeInfo my_info = {
333 sizeof(ModestMsgEditWindowClass),
334 NULL, /* base init */
335 NULL, /* base finalize */
336 (GClassInitFunc) modest_msg_edit_window_class_init,
337 NULL, /* class finalize */
338 NULL, /* class data */
339 sizeof(ModestMsgEditWindow),
341 (GInstanceInitFunc) modest_msg_edit_window_init,
344 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
345 "ModestMsgEditWindow",
353 save_state (ModestWindow *self)
355 modest_widget_memory_save (modest_runtime_get_conf(),
356 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
361 restore_settings (ModestMsgEditWindow *self)
363 ModestConf *conf = NULL;
365 conf = modest_runtime_get_conf ();
367 /* Dim at start clipboard actions */
368 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
373 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
375 GObjectClass *gobject_class;
376 ModestWindowClass *modest_window_class;
377 gobject_class = (GObjectClass*) klass;
378 modest_window_class = (ModestWindowClass*) klass;
380 parent_class = g_type_class_peek_parent (klass);
381 gobject_class->finalize = modest_msg_edit_window_finalize;
383 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
384 modest_window_class->save_state_func = save_state;
385 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
387 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
391 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
393 ModestMsgEditWindowPrivate *priv;
394 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
396 priv->msg_body = NULL;
397 priv->from_field = NULL;
398 priv->to_field = NULL;
399 priv->cc_field = NULL;
400 priv->bcc_field = NULL;
401 priv->subject_field = NULL;
402 priv->attachments = TNY_LIST (tny_simple_list_new ());
403 priv->images = TNY_LIST (tny_simple_list_new ());
404 priv->images_size = 0;
405 priv->images_count = 0;
408 priv->cc_caption = NULL;
409 priv->bcc_caption = NULL;
410 priv->update_caption_visibility = FALSE;
412 priv->priority_flags = 0;
414 priv->find_toolbar = NULL;
415 priv->last_search = NULL;
417 priv->draft_msg = NULL;
418 priv->outbox_msg = NULL;
419 priv->msg_uid = NULL;
421 priv->can_undo = FALSE;
422 priv->can_redo = FALSE;
423 priv->clipboard_change_handler_id = 0;
424 priv->default_clipboard_change_handler_id = 0;
425 priv->account_removed_handler_id = 0;
426 priv->clipboard_owner_idle = 0;
427 priv->clipboard_text = NULL;
430 priv->scroll_drag_timeout_id = 0;
431 priv->correct_scroll_idle = 0;
432 priv->last_upper = 0.0;
434 priv->font_dialog = NULL;
435 priv->app_menu = NULL;
437 priv->references = NULL;
438 priv->in_reply_to = NULL;
440 if (!is_wp_text_buffer_started) {
441 is_wp_text_buffer_started = TRUE;
442 wp_text_buffer_library_init ();
447 hildon_program_add_window (hildon_program_get_instance(),
452 multimailbox_get_default_mailbox (const gchar *account_name)
454 gchar *transport_account;
455 gchar *result = NULL;
457 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
459 TNY_ACCOUNT_TYPE_TRANSPORT);
460 if (transport_account) {
462 ModestProtocolRegistry *registry;
464 registry = modest_runtime_get_protocol_registry ();
466 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
467 MODEST_ACCOUNT_PROTO, TRUE);
469 ModestProtocol *protocol =
470 modest_protocol_registry_get_protocol_by_name (registry,
471 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
473 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
474 ModestPairList *pair_list;
476 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
479 ModestPair *pair = (ModestPair *) pair_list->data;
480 result = g_strdup ((const gchar *) pair->first);
481 modest_pair_list_free (pair_list);
492 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
494 static ModestPairList*
495 get_transports (void)
497 GSList *transports = NULL;
499 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
500 GSList *accounts = modest_account_mgr_account_names (account_mgr,
501 TRUE /* only enabled accounts. */);
503 GSList *cursor = accounts;
505 gchar *account_name = cursor->data;
508 gchar *transport_account;
509 gboolean multi_mailbox = FALSE;
510 ModestProtocol *protocol = NULL;
512 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
514 transport_account = modest_account_mgr_get_server_account_name
515 (modest_runtime_get_account_mgr (),
517 TNY_ACCOUNT_TYPE_TRANSPORT);
518 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
519 ModestPairList *pair_list;
520 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
523 transports = g_slist_concat (transports, pair_list);
524 multi_mailbox = TRUE;
529 if (!multi_mailbox) {
530 gchar *from_string = NULL;
532 from_string = modest_account_mgr_get_from_string (account_mgr,
534 if (from_string && account_name) {
535 gchar *name = account_name;
536 ModestPair *pair = modest_pair_new ((gpointer) name,
537 (gpointer) from_string , TRUE);
538 transports = g_slist_prepend (transports, pair);
543 cursor = cursor->next;
545 g_slist_free (accounts); /* only free the accounts, not the elements,
546 * because they are used in the pairlist */
550 static void window_focus (GtkWindow *window,
554 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
558 scroll_drag_timeout (gpointer userdata)
560 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
561 ModestMsgEditWindowPrivate *priv;
563 /* It could happen that the window was already closed */
564 if (!GTK_WIDGET_VISIBLE (win))
567 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
569 correct_scroll_without_drag_check (win, TRUE);
571 priv->scroll_drag_timeout_id = 0;
577 correct_scroll_without_drag_check_idle (gpointer userdata)
579 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
580 ModestMsgEditWindowPrivate *priv;
582 GdkRectangle rectangle;
583 gint offset_min, offset_max;
587 /* It could happen that the window was already closed */
588 if (!GTK_WIDGET_VISIBLE (w))
591 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
593 insert = gtk_text_buffer_get_insert (priv->text_buffer);
594 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
596 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
597 offset_min = priv->msg_body->allocation.y + rectangle.y;
598 offset_max = offset_min + rectangle.height;
600 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
601 offset_min = MAX (offset_min - 48, 0);
602 offset_max = MIN (offset_max + 48, vadj->upper);
604 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
606 priv->correct_scroll_idle = 0;
611 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
613 ModestMsgEditWindowPrivate *priv;
615 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
617 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
620 if (priv->correct_scroll_idle > 0) {
624 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
625 (GSourceFunc) correct_scroll_without_drag_check_idle,
631 correct_scroll (ModestMsgEditWindow *w)
633 ModestMsgEditWindowPrivate *priv;
635 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
636 if (gtk_grab_get_current () == priv->msg_body) {
637 if (priv->scroll_drag_timeout_id == 0) {
638 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
640 (GSourceFunc) scroll_drag_timeout,
647 correct_scroll_without_drag_check (w, TRUE);
651 text_buffer_end_user_action (GtkTextBuffer *buffer,
652 ModestMsgEditWindow *userdata)
655 correct_scroll (userdata);
659 text_buffer_mark_set (GtkTextBuffer *buffer,
662 ModestMsgEditWindow *userdata)
664 gtk_text_buffer_begin_user_action (buffer);
665 gtk_text_buffer_end_user_action (buffer);
669 cut_clipboard_check (GtkTextView *text_view,
672 GtkTextBuffer *buffer;
674 buffer = gtk_text_view_get_buffer (text_view);
675 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
676 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
681 copy_clipboard_check (GtkTextView *text_view,
684 GtkTextBuffer *buffer;
686 buffer = gtk_text_view_get_buffer (text_view);
687 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
688 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
693 attachment_deleted (ModestAttachmentsView *attachments_view,
696 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
701 connect_signals (ModestMsgEditWindow *obj)
703 ModestMsgEditWindowPrivate *priv;
705 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
707 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
708 G_CALLBACK (text_buffer_refresh_attributes), obj);
709 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
710 G_CALLBACK (text_buffer_can_undo), obj);
711 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
712 G_CALLBACK (text_buffer_can_redo), obj);
713 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
714 G_CALLBACK (body_changed), obj);
715 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
716 G_CALLBACK (body_changed), obj);
717 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
718 G_CALLBACK (text_buffer_end_user_action), obj);
719 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
720 G_CALLBACK (text_buffer_mark_set), obj);
721 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
722 G_CALLBACK (text_buffer_apply_tag), obj);
723 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
724 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
725 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
726 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
727 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
728 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
730 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
731 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
732 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
733 G_CALLBACK (from_field_changed), obj);
735 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
736 G_CALLBACK (msg_body_focus), obj);
737 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
738 G_CALLBACK (msg_body_focus), obj);
739 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
740 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
741 "changed", G_CALLBACK (recpt_field_changed), obj);
742 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
743 "changed", G_CALLBACK (recpt_field_changed), obj);
744 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
745 "changed", G_CALLBACK (recpt_field_changed), obj);
746 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
747 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
748 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
750 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
751 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
753 priv->clipboard_change_handler_id =
754 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
755 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
756 priv->default_clipboard_change_handler_id =
757 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
758 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
760 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
761 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
762 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
766 init_wp_text_view_style ()
768 static gboolean initialized = FALSE;
771 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
777 init_window (ModestMsgEditWindow *obj)
779 GtkWidget *to_caption, *subject_caption;
780 GtkWidget *main_vbox;
781 GtkWidget *add_attachment_align;
782 ModestMsgEditWindowPrivate *priv;
783 GtkActionGroup *action_group;
784 ModestWindowPrivate *parent_priv;
785 GdkPixbuf *window_icon = NULL;
786 GError *error = NULL;
788 GtkSizeGroup *title_size_group;
789 GtkSizeGroup *value_size_group;
790 GtkWidget *attachment_icon;
791 GtkWidget *window_box;
792 GtkWidget *window_align;
793 #if (GTK_MINOR_VERSION >= 10)
794 GdkAtom deserialize_type;
797 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
798 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
800 parent_priv->ui_manager = gtk_ui_manager_new();
801 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
802 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
804 /* Add common actions */
805 gtk_action_group_add_actions (action_group,
806 modest_msg_edit_action_entries,
807 G_N_ELEMENTS (modest_msg_edit_action_entries),
809 gtk_action_group_add_actions (action_group,
810 hildon2_msg_edit_action_entries,
811 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
813 gtk_action_group_add_toggle_actions (action_group,
814 modest_msg_edit_toggle_action_entries,
815 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
817 gtk_action_group_add_radio_actions (action_group,
818 modest_msg_edit_alignment_radio_action_entries,
819 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
821 G_CALLBACK (modest_ui_actions_on_change_justify),
823 gtk_action_group_add_radio_actions (action_group,
824 modest_msg_edit_priority_action_entries,
825 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
827 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
829 gtk_action_group_add_radio_actions (action_group,
830 modest_msg_edit_file_format_action_entries,
831 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
832 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
833 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
835 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
836 g_object_unref (action_group);
838 /* Load the UI definition */
839 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
842 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
843 g_clear_error (&error);
846 /* Add accelerators */
847 gtk_window_add_accel_group (GTK_WINDOW (obj),
848 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
850 parent_priv->menubar = NULL;
852 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
853 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
855 /* Note: This ModestPairList* must exist for as long as the picker
856 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
857 * so it can't know how to manage its memory. */
858 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
859 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
861 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
862 _("mail_va_from"), priv->from_field);
864 priv->to_field = modest_recpt_editor_new ();
865 priv->cc_field = modest_recpt_editor_new ();
866 priv->bcc_field = modest_recpt_editor_new ();
867 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
868 priv->priority_icon = gtk_image_new ();
869 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
870 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
871 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
872 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
873 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
874 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
875 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
876 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
877 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
878 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
879 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
880 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
881 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
882 add_attachment_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
883 gtk_alignment_set_padding (GTK_ALIGNMENT (add_attachment_align), 0, 0, MODEST_MARGIN_DEFAULT, 0);
884 gtk_container_add (GTK_CONTAINER (add_attachment_align), priv->add_attachment_button);
885 gtk_box_pack_start (GTK_BOX (priv->subject_box), add_attachment_align, FALSE, FALSE, 0);
886 priv->attachments_view = modest_attachments_view_new (NULL);
887 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
888 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
890 priv->header_box = gtk_vbox_new (FALSE, 0);
892 to_caption = modest_maemo_utils_create_captioned_with_size_type
893 (title_size_group, value_size_group,
894 _("mail_va_to"), FALSE, priv->to_field,
895 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
896 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
897 (title_size_group, value_size_group,
898 _("mail_va_cc"), FALSE, priv->cc_field,
899 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
900 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
901 (title_size_group, value_size_group,
902 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
903 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
904 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
905 _("mail_va_subject"), FALSE, priv->subject_box);
906 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
907 _("mail_va_attachment"),
909 priv->attachments_view,
910 HILDON_SIZE_AUTO_WIDTH |
911 HILDON_SIZE_AUTO_HEIGHT);
912 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
913 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
914 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
915 g_object_unref (title_size_group);
916 g_object_unref (value_size_group);
918 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
919 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
920 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
921 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
922 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
923 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
924 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
926 init_wp_text_view_style ();
928 priv->msg_body = modest_wp_text_view_new ();
931 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
932 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
933 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
934 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
935 #if (GTK_MINOR_VERSION >= 10)
936 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
937 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
939 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
940 deserialize_type, TRUE);
942 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
944 priv->find_toolbar = hildon_find_toolbar_new (NULL);
945 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
947 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
949 priv->pannable = hildon_pannable_area_new ();
951 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
952 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
953 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
955 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
956 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
957 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
959 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
960 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
962 window_box = gtk_vbox_new (FALSE, 0);
963 gtk_container_add (GTK_CONTAINER(obj), window_box);
965 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
967 /* Set window icon */
968 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
970 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
971 g_object_unref (window_icon);
976 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
978 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
980 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
981 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
982 priv->clipboard_change_handler_id))
983 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
984 priv->clipboard_change_handler_id);
985 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
986 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
987 priv->default_clipboard_change_handler_id))
988 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
989 priv->default_clipboard_change_handler_id);
991 if (priv->account_removed_handler_id &&
992 g_signal_handler_is_connected (modest_runtime_get_account_store (),
993 priv->account_removed_handler_id))
994 g_signal_handler_disconnect(modest_runtime_get_account_store (),
995 priv->account_removed_handler_id);
999 modest_msg_edit_window_finalize (GObject *obj)
1001 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1003 /* Sanity check: shouldn't be needed, the window mgr should
1004 call this function before */
1005 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1007 if (priv->font_dialog != NULL) {
1008 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1011 if (priv->clipboard_text != NULL) {
1012 g_free (priv->clipboard_text);
1013 priv->clipboard_text = NULL;
1016 if (priv->draft_msg != NULL) {
1017 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1018 if (TNY_IS_HEADER (header)) {
1019 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1020 modest_window_mgr_unregister_header (mgr, header);
1022 g_object_unref (priv->draft_msg);
1023 priv->draft_msg = NULL;
1025 if (priv->outbox_msg != NULL) {
1026 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1027 if (TNY_IS_HEADER (header)) {
1028 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1029 modest_window_mgr_unregister_header (mgr, header);
1031 g_object_unref (priv->outbox_msg);
1032 priv->outbox_msg = NULL;
1034 if (priv->correct_scroll_idle > 0) {
1035 g_source_remove (priv->correct_scroll_idle);
1036 priv->correct_scroll_idle = 0;
1038 if (priv->scroll_drag_timeout_id > 0) {
1039 g_source_remove (priv->scroll_drag_timeout_id);
1040 priv->scroll_drag_timeout_id = 0;
1042 if (priv->clipboard_owner_idle > 0) {
1043 g_source_remove (priv->clipboard_owner_idle);
1044 priv->clipboard_owner_idle = 0;
1046 if (priv->original_account_name)
1047 g_free (priv->original_account_name);
1048 if (priv->original_mailbox)
1049 g_free (priv->original_mailbox);
1050 g_free (priv->msg_uid);
1051 g_free (priv->last_search);
1052 g_free (priv->references);
1053 g_free (priv->in_reply_to);
1054 g_object_unref (priv->faces_model);
1055 g_object_unref (priv->sizes_model);
1056 g_object_unref (priv->attachments);
1057 g_object_unref (priv->images);
1059 /* This had to stay alive for as long as the picker that used it: */
1060 modest_pair_list_free (priv->from_field_protos);
1062 G_OBJECT_CLASS(parent_class)->finalize (obj);
1066 pixbuf_size_prepared (GdkPixbufLoader *loader,
1069 ModestMsgEditWindow *self)
1071 gint new_height, new_width;
1074 new_height = height;
1078 if (width > IMAGE_MAX_WIDTH) {
1079 new_height = height * IMAGE_MAX_WIDTH / width;
1080 new_width = IMAGE_MAX_WIDTH;
1083 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1087 pixbuf_from_stream (TnyStream *stream,
1088 const gchar *mime_type,
1089 guint64 *stream_size,
1090 ModestMsgEditWindow *self)
1092 GdkPixbufLoader *loader;
1095 GError *error = NULL;
1099 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1101 if (loader == NULL) {
1106 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1108 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1110 tny_stream_reset (TNY_STREAM (stream));
1111 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1112 unsigned char read_buffer[128];
1114 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1116 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1119 /* Allow some UI responsiveness */
1120 while (gtk_events_pending ())
1121 gtk_main_iteration ();
1123 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1125 gdk_pixbuf_loader_close (loader, &error);
1128 g_error_free (error);
1129 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1131 g_object_ref (pixbuf);
1132 g_object_unref (loader);
1137 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1138 GdkPixbuf *new_pixbuf;
1140 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1141 gdk_pixbuf_get_width (pixbuf);
1142 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1143 g_object_unref (pixbuf);
1144 pixbuf = new_pixbuf;
1148 *stream_size = size;
1154 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1156 ModestMsgEditWindowPrivate *priv;
1159 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1161 g_object_ref (self);
1162 for (iter = tny_list_create_iterator (attachments);
1163 !tny_iterator_is_done (iter);
1164 tny_iterator_next (iter)) {
1165 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1166 const gchar *cid = tny_mime_part_get_content_id (part);
1167 const gchar *mime_type = tny_mime_part_get_content_type (part);
1168 if ((cid != NULL)&&(mime_type != NULL)) {
1169 guint64 stream_size;
1170 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1171 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1174 g_object_unref (stream);
1176 if (pixbuf != NULL) {
1177 priv->images_count ++;
1178 priv->images_size += stream_size;
1179 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1180 g_object_unref (pixbuf);
1183 g_object_unref (part);
1185 g_object_unref (iter);
1186 g_object_unref (self);
1190 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1192 TnyMimePart *parent = NULL;
1193 const gchar *content_type = NULL;
1194 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1196 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1198 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1199 parent = g_object_ref (msg);
1200 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1201 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1204 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1205 iter = tny_list_create_iterator (parts);
1206 while (!tny_iterator_is_done (iter)) {
1208 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1209 content_type = tny_mime_part_get_content_type (part);
1210 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1214 g_object_unref (part);
1216 tny_iterator_next (iter);
1218 g_object_unref (iter);
1219 g_object_unref (parts);
1222 if (parent != NULL) {
1223 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1226 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1227 iter = tny_list_create_iterator (parts);
1228 while (!tny_iterator_is_done (iter)) {
1230 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1231 content_type = tny_mime_part_get_content_type (part);
1232 if (content_type && g_str_has_prefix (content_type, "image/")) {
1233 tny_list_prepend (priv->images, (GObject *) part);
1235 g_object_unref (part);
1236 tny_iterator_next (iter);
1238 g_object_unref (iter);
1239 g_object_unref (parts);
1240 g_object_unref (parent);
1245 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1248 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1250 for (iter = tny_list_create_iterator (attachments) ;
1251 !tny_iterator_is_done (iter);
1252 tny_iterator_next (iter)) {
1253 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1254 const gchar *cid = tny_mime_part_get_content_id (part);
1256 char *invalid = NULL;
1257 gint int_cid = strtol (cid, &invalid, 10);
1258 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1259 priv->next_cid = int_cid + 1;
1262 g_object_unref (part);
1264 g_object_unref (iter);
1268 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1271 gchar *to, *cc, *bcc, *subject;
1273 ModestMsgEditWindowPrivate *priv;
1274 ModestWindowPrivate *parent_priv;
1276 TnyHeaderFlags priority_flags;
1277 TnyFolder *msg_folder;
1278 gboolean is_html = FALSE;
1279 gboolean field_view_set;
1281 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1282 g_return_if_fail (TNY_IS_MSG (msg));
1284 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1285 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1287 header = tny_msg_get_header (msg);
1288 to = tny_header_dup_to (header);
1289 cc = tny_header_dup_cc (header);
1290 bcc = tny_header_dup_bcc (header);
1291 subject = tny_header_dup_subject (header);
1293 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1294 priority_flags = tny_header_get_priority (header);
1297 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1299 field_view_set = TRUE;
1301 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1302 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1303 gtk_widget_show (priv->cc_caption);
1304 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1305 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1306 gtk_widget_hide (priv->cc_caption);
1307 field_view_set = FALSE;
1309 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1311 field_view_set = TRUE;
1313 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1314 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1315 gtk_widget_show (priv->bcc_caption);
1316 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1317 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1318 gtk_widget_hide (priv->bcc_caption);
1319 field_view_set = FALSE;
1321 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1325 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1326 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1329 update_window_title (self);
1331 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1332 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1334 if ((body == NULL)||(body[0] == '\0')) {
1336 body = modest_text_utils_convert_to_html ("");
1339 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1340 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1343 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1346 /* Add attachments to the view */
1347 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1348 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1349 if (tny_list_get_length (priv->attachments) == 0) {
1350 gtk_widget_hide (priv->attachments_caption);
1352 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1353 gtk_widget_show_all (priv->attachments_caption);
1355 get_related_images (self, msg);
1356 update_next_cid (self, priv->attachments);
1357 update_next_cid (self, priv->images);
1358 replace_with_images (self, priv->images);
1360 if (preserve_is_rich && !is_html) {
1361 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1362 /* Get the default format required from configuration */
1363 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1364 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1367 /* Set the default focus depending on having already a To: field or not */
1368 if ((!to)||(*to == '\0')) {
1369 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1371 gtk_widget_grab_focus (priv->msg_body);
1374 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1376 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1377 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1379 modest_msg_edit_window_set_modified (self, FALSE);
1381 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1382 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1383 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1384 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1386 if (priv->msg_uid) {
1387 g_free (priv->msg_uid);
1388 priv->msg_uid = NULL;
1391 /* we should set a reference to the incoming message if it is a draft */
1392 msg_folder = tny_msg_get_folder (msg);
1394 if (modest_tny_folder_is_local_folder (msg_folder)) {
1395 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1396 if (type == TNY_FOLDER_TYPE_INVALID)
1397 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1399 if (type == TNY_FOLDER_TYPE_DRAFTS)
1400 priv->draft_msg = g_object_ref(msg);
1401 if (type == TNY_FOLDER_TYPE_OUTBOX)
1402 priv->outbox_msg = g_object_ref(msg);
1403 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1405 g_object_unref (msg_folder);
1416 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1418 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1419 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1420 GtkWidget *placeholder;
1421 GtkWidget *tool_item;
1426 GtkWidget *sizes_menu;
1427 GtkWidget *fonts_menu;
1433 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1434 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1435 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1436 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1438 /* Font color placeholder */
1439 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1440 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1443 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1444 priv->font_color_button = hildon_color_button_new ();
1445 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1446 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1447 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1448 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1449 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1450 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1451 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1452 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1454 G_CALLBACK (modest_msg_edit_window_color_button_change),
1457 /* Font size and face placeholder */
1458 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1459 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1461 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1462 priv->size_tool_button_label = gtk_label_new (NULL);
1463 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1464 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1465 size_text, "</span>", NULL);
1466 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1467 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1469 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1470 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1471 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1472 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1473 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1474 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1475 gtk_widget_set_sensitive (arrow, FALSE);
1476 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1477 sizes_menu = gtk_menu_new ();
1478 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1479 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1482 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1483 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1485 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1489 if (wp_font_size[size_index] == 12)
1490 priv->current_size_index = size_index;
1494 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1495 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1496 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1497 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1498 priv->font_size_toolitem = tool_item;
1501 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1502 priv->font_tool_button_label = gtk_label_new (NULL);
1503 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1504 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1505 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1507 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1508 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1509 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1510 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1511 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1512 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1513 gtk_widget_set_sensitive (arrow, FALSE);
1514 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1515 fonts_menu = gtk_menu_new ();
1516 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1517 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1520 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1522 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1523 0, wp_get_font_name (font_index),
1526 if (font_index == DEFAULT_FONT)
1527 priv->current_face_index = font_index;
1529 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1530 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1531 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1532 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1533 priv->font_face_toolitem = tool_item;
1535 /* Set expand and homogeneous for remaining items */
1536 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1537 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1538 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1539 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1540 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1541 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1542 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1543 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1544 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1546 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1547 will not show the tool items added to the placeholders) */
1548 gtk_widget_show_all (parent_priv->toolbar);
1550 /* Set the no show all *after* showing all items. We do not
1551 want the toolbar to be shown with a show all because it
1552 could go agains the gconf setting regarding showing or not
1553 the toolbar of the editor window */
1554 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1560 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1563 ModestWindowPrivate *parent_priv;
1564 ModestMsgEditWindowPrivate *priv;
1565 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1566 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1567 ModestWindowMgr *mgr = NULL;
1569 g_return_val_if_fail (msg, NULL);
1570 g_return_val_if_fail (account_name, NULL);
1572 mgr = modest_runtime_get_window_mgr ();
1574 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1576 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1577 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1579 /* Menubar. Update the state of some toggles */
1580 priv->from_field_protos = get_transports ();
1581 priv->original_mailbox = NULL;
1582 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1583 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1584 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1585 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1586 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1587 priv->original_mailbox = g_strdup (mailbox);
1588 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1589 /* We set the first mailbox as the active mailbox */
1590 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1591 if (priv->original_mailbox != NULL)
1592 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1593 (gpointer) priv->original_mailbox);
1595 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1596 (gpointer) account_name);
1598 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1600 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1601 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1603 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1604 hildon_touch_selector_get_current_text
1605 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1606 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1607 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1610 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1612 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1614 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1615 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1617 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1619 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1620 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1621 /* Add common dimming rules */
1622 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1623 modest_msg_edit_window_toolbar_dimming_entries,
1624 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1625 MODEST_WINDOW (obj));
1626 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1627 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1628 MODEST_WINDOW (obj));
1629 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1630 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1631 MODEST_WINDOW (obj));
1632 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1633 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1634 MODEST_WINDOW (obj));
1635 /* Insert dimming rules group for this window */
1636 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1637 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1639 /* Setup app menu */
1640 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1642 /* Checks the dimming rules */
1643 g_object_unref (toolbar_rules_group);
1644 g_object_unref (clipboard_rules_group);
1645 gtk_widget_hide (priv->priority_icon);
1646 gtk_widget_queue_resize (priv->subject_box);
1647 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1649 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1651 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1652 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1653 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1654 priv->update_caption_visibility = TRUE;
1656 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1658 /* Track account-removed signal, this window should be closed
1659 in the case we're creating a mail associated to the account
1661 priv->account_removed_handler_id =
1662 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1664 G_CALLBACK(on_account_removed),
1667 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1669 return (ModestWindow*) obj;
1673 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1675 GString **string_buffer = (GString **) user_data;
1677 *string_buffer = g_string_append (*string_buffer, buffer);
1683 * @result: A new string which should be freed with g_free().
1686 get_formatted_data (ModestMsgEditWindow *edit_window)
1688 ModestMsgEditWindowPrivate *priv;
1689 GString *string_buffer = g_string_new ("");
1691 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1693 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1695 modest_text_utils_hyperlinkify (string_buffer);
1697 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1699 return g_string_free (string_buffer, FALSE);
1704 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1707 const gchar *account_name;
1708 ModestMsgEditWindowPrivate *priv;
1709 TnyIterator *att_iter;
1710 const gchar *picker_active_id;
1712 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1714 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1716 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1717 g_return_val_if_fail (picker_active_id, NULL);
1718 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1720 /* don't free these (except from) */
1721 data = g_slice_new0 (MsgData);
1722 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1723 data->account_name = g_strdup (account_name);
1724 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1725 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1726 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1727 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1728 data->references = g_strdup (priv->references);
1729 data->in_reply_to = g_strdup (priv->in_reply_to);
1730 if (priv->draft_msg) {
1731 data->draft_msg = g_object_ref (priv->draft_msg);
1732 } else if (priv->outbox_msg) {
1733 data->draft_msg = g_object_ref (priv->outbox_msg);
1735 data->draft_msg = NULL;
1738 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1740 gtk_text_buffer_get_bounds (buf, &b, &e);
1741 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1743 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1744 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1746 data->html_body = NULL;
1748 /* deep-copy the data */
1749 att_iter = tny_list_create_iterator (priv->attachments);
1750 data->attachments = NULL;
1751 while (!tny_iterator_is_done (att_iter)) {
1752 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1753 if (!(TNY_IS_MIME_PART(part))) {
1754 g_warning ("strange data in attachment list");
1755 g_object_unref (part);
1756 tny_iterator_next (att_iter);
1759 data->attachments = g_list_append (data->attachments,
1761 tny_iterator_next (att_iter);
1763 g_object_unref (att_iter);
1765 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1766 att_iter = tny_list_create_iterator (priv->images);
1767 data->images = NULL;
1768 while (!tny_iterator_is_done (att_iter)) {
1769 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1771 if (!(TNY_IS_MIME_PART(part))) {
1772 g_warning ("strange data in attachment list");
1773 g_object_unref (part);
1774 tny_iterator_next (att_iter);
1777 cid = tny_mime_part_get_content_id (part);
1779 gchar *image_tag_id;
1780 GtkTextTag *image_tag;
1782 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1783 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1784 g_free (image_tag_id);
1786 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1788 ((gtk_text_iter_has_tag (&iter, image_tag))||
1789 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1790 data->images = g_list_append (data->images,
1791 g_object_ref (part));
1793 g_object_unref (part);
1794 tny_iterator_next (att_iter);
1796 g_object_unref (att_iter);
1798 data->priority_flags = priv->priority_flags;
1805 unref_gobject (GObject *obj, gpointer data)
1807 if (!G_IS_OBJECT(obj))
1809 g_object_unref (obj);
1813 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1816 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1824 g_free (data->from);
1825 g_free (data->subject);
1826 g_free (data->plain_body);
1827 g_free (data->html_body);
1828 g_free (data->account_name);
1829 g_free (data->references);
1830 g_free (data->in_reply_to);
1832 if (data->draft_msg != NULL) {
1833 g_object_unref (data->draft_msg);
1834 data->draft_msg = NULL;
1837 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1838 g_list_free (data->attachments);
1839 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1840 g_list_free (data->images);
1842 g_slice_free (MsgData, data);
1846 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1848 guint64 *parts_size)
1850 ModestMsgEditWindowPrivate *priv;
1852 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1854 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1856 /* TODO: add images */
1857 *parts_size += priv->images_size;
1858 *parts_count += priv->images_count;
1863 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1866 ModestMsgEditWindowPrivate *priv = NULL;
1867 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1869 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1871 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1873 return MODEST_MSG_EDIT_FORMAT_HTML;
1875 return MODEST_MSG_EDIT_FORMAT_TEXT;
1879 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1880 ModestMsgEditFormat format)
1882 ModestMsgEditWindowPrivate *priv;
1884 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1885 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1888 case MODEST_MSG_EDIT_FORMAT_HTML:
1889 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1891 case MODEST_MSG_EDIT_FORMAT_TEXT:
1892 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1895 g_return_if_reached ();
1899 ModestMsgEditFormatState *
1900 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1902 ModestMsgEditFormatState *format_state = NULL;
1903 ModestMsgEditWindowPrivate *priv;
1904 WPTextBufferFormat *buffer_format;
1906 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1908 buffer_format = g_new0 (WPTextBufferFormat, 1);
1909 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1911 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1913 format_state = g_new0 (ModestMsgEditFormatState, 1);
1914 format_state->bold = buffer_format->bold&0x1;
1915 format_state->italics = buffer_format->italic&0x1;
1916 format_state->bullet = buffer_format->bullet&0x1;
1917 format_state->color = buffer_format->color;
1918 format_state->font_size = buffer_format->font_size;
1919 format_state->font_family = wp_get_font_name (buffer_format->font);
1920 format_state->justification = buffer_format->justification;
1921 g_free (buffer_format);
1923 return format_state;
1928 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1929 const ModestMsgEditFormatState *format_state)
1931 ModestMsgEditWindowPrivate *priv;
1932 WPTextBufferFormat *buffer_format;
1933 WPTextBufferFormat *current_format;
1935 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1936 g_return_if_fail (format_state != NULL);
1938 buffer_format = g_new0 (WPTextBufferFormat, 1);
1939 current_format = g_new0 (WPTextBufferFormat, 1);
1941 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1942 gtk_widget_grab_focus (priv->msg_body);
1943 buffer_format->bold = (format_state->bold != FALSE);
1944 buffer_format->italic = (format_state->italics != FALSE);
1945 buffer_format->color = format_state->color;
1946 buffer_format->font_size = format_state->font_size;
1947 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1948 buffer_format->justification = format_state->justification;
1949 buffer_format->bullet = format_state->bullet;
1951 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1953 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1954 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1955 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1956 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1957 buffer_format->cs.font = (buffer_format->font != current_format->font);
1958 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1959 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1961 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1962 if (buffer_format->cs.bold) {
1963 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1964 GINT_TO_POINTER (buffer_format->bold&0x1));
1966 if (buffer_format->cs.italic) {
1967 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1968 GINT_TO_POINTER (buffer_format->italic&0x1));
1970 if (buffer_format->cs.color) {
1971 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1972 GINT_TO_POINTER (&(buffer_format->color)));
1974 if (buffer_format->cs.font_size) {
1975 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1976 GINT_TO_POINTER (buffer_format->font_size));
1978 if (buffer_format->cs.justification) {
1979 switch (buffer_format->justification) {
1980 case GTK_JUSTIFY_LEFT:
1981 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1982 GINT_TO_POINTER(TRUE));
1984 case GTK_JUSTIFY_CENTER:
1985 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1986 GINT_TO_POINTER(TRUE));
1988 case GTK_JUSTIFY_RIGHT:
1989 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1990 GINT_TO_POINTER(TRUE));
1997 if (buffer_format->cs.font) {
1998 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1999 GINT_TO_POINTER (buffer_format->font));
2001 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2002 if (buffer_format->cs.bullet) {
2003 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2004 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2006 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2008 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2010 g_free (buffer_format);
2011 g_free (current_format);
2013 /* Check dimming rules */
2014 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2015 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2019 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2021 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2023 ModestWindowPrivate *parent_priv;
2024 ModestMsgEditWindowPrivate *priv;
2026 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2027 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2029 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2030 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2031 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2032 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2034 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2035 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2036 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2039 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2041 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2042 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2044 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2045 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2047 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2048 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2051 switch (buffer_format->justification)
2053 case GTK_JUSTIFY_LEFT:
2054 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2056 case GTK_JUSTIFY_CENTER:
2057 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2059 case GTK_JUSTIFY_RIGHT:
2060 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2067 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2069 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2070 G_CALLBACK (modest_msg_edit_window_color_button_change),
2072 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2073 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2074 G_CALLBACK (modest_msg_edit_window_color_button_change),
2077 if (priv->current_size_index != buffer_format->font_size) {
2081 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2082 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2086 priv->current_size_index = buffer_format->font_size;
2088 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2089 markup = g_strconcat ("<span font_family='Sans'>",
2090 size_text, "</span>", NULL);
2092 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2096 gtk_tree_path_free (path);
2099 if (priv->current_face_index != buffer_format->font) {
2103 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2104 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2108 priv->current_face_index = buffer_format->font;
2109 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2110 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2111 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2118 g_free (buffer_format);
2122 #ifdef MODEST_HILDON_VERSION_0
2124 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2127 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2128 ModestMsgEditWindowPrivate *priv;
2129 GtkWidget *dialog = NULL;
2131 GdkColor *new_color = NULL;
2133 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2134 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2136 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2137 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2138 g_free (buffer_format);
2140 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2141 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2142 if (new_color != NULL) {
2143 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2144 (gpointer) new_color);
2147 gtk_widget_destroy (dialog);
2152 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2155 ModestMsgEditWindowPrivate *priv;
2156 GtkWidget *dialog = NULL;
2158 GdkColor *old_color = NULL;
2159 const GdkColor *new_color = NULL;
2161 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2162 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2164 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2165 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2167 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2168 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2169 if (new_color != NULL)
2170 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2172 gtk_widget_destroy (dialog);
2178 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2181 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2182 ModestMsgEditWindowPrivate *priv;
2183 GtkWidget *dialog = NULL;
2185 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2186 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2188 dialog = hildon_color_chooser_new ();
2189 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2190 g_free (buffer_format);
2192 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2194 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2195 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2198 gtk_widget_destroy (dialog);
2203 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2206 ModestMsgEditWindowPrivate *priv;
2207 GtkWidget *dialog = NULL;
2208 GdkColor *old_color = NULL;
2210 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2211 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2213 dialog = hildon_color_chooser_new ();
2214 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2216 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2218 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2219 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2221 gtk_widget_destroy (dialog);
2224 #endif /*!MODEST_HILDON_VERSION_0*/
2229 create_stream_for_uri (const gchar* uri)
2234 TnyStream *result = NULL;
2236 GnomeVFSHandle *handle = NULL;
2237 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2238 if (test == GNOME_VFS_OK) {
2239 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2240 /* Streams over OBEX (Bluetooth) are not seekable but
2241 * we expect them to be (we might need to read them
2242 * several times). So if this is a Bluetooth URI just
2243 * read the whole file into memory (this is not a fast
2244 * protocol so we can assume that these files are not
2245 * going to be very big) */
2246 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2247 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2248 TnyStream *memstream = tny_camel_mem_stream_new ();
2249 tny_stream_write_to_stream (vfssstream, memstream);
2250 g_object_unref (vfssstream);
2253 result = vfssstream;
2261 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2264 ModestMsgEditWindowPrivate *priv;
2265 GtkWidget *dialog = NULL;
2267 GSList *uris = NULL;
2268 GSList *uri_node = NULL;
2270 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2272 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2273 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2274 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2276 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2278 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2279 GTK_WINDOW (dialog), GTK_WINDOW (window));
2281 response = gtk_dialog_run (GTK_DIALOG (dialog));
2283 case GTK_RESPONSE_OK:
2285 gchar *current_folder;
2286 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2287 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2288 if (current_folder && current_folder != '\0') {
2290 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2291 current_folder, &err);
2293 g_debug ("Error storing latest used folder: %s", err->message);
2297 g_free (current_folder);
2303 gtk_widget_destroy (dialog);
2305 g_object_ref (window);
2306 /* The operation could take some time so allow the dialog to be closed */
2307 while (gtk_events_pending ())
2308 gtk_main_iteration ();
2310 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2312 GnomeVFSHandle *handle = NULL;
2313 GnomeVFSResult result;
2314 GtkTextIter position;
2315 GtkTextMark *insert_mark;
2317 uri = (const gchar *) uri_node->data;
2318 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2319 if (result == GNOME_VFS_OK) {
2321 GnomeVFSFileInfo *info;
2322 gchar *filename, *basename, *escaped_filename;
2323 TnyMimePart *mime_part;
2325 const gchar *mime_type = NULL;
2326 GnomeVFSURI *vfs_uri;
2327 guint64 stream_size;
2329 gnome_vfs_close (handle);
2330 vfs_uri = gnome_vfs_uri_new (uri);
2332 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2333 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2334 g_free (escaped_filename);
2335 gnome_vfs_uri_unref (vfs_uri);
2336 info = gnome_vfs_file_info_new ();
2338 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2339 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2341 mime_type = gnome_vfs_file_info_get_mime_type (info);
2343 mime_part = tny_platform_factory_new_mime_part
2344 (modest_runtime_get_platform_factory ());
2346 TnyStream *stream = create_stream_for_uri (uri);
2348 if (stream == NULL) {
2350 modest_platform_information_banner (NULL, NULL,
2351 _FM("sfil_ib_opening_not_allowed"));
2353 g_object_unref (mime_part);
2354 gnome_vfs_file_info_unref (info);
2358 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2360 content_id = g_strdup_printf ("%d", priv->next_cid);
2361 tny_mime_part_set_content_id (mime_part, content_id);
2362 g_free (content_id);
2365 basename = g_path_get_basename (filename);
2366 tny_mime_part_set_filename (mime_part, basename);
2369 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2371 if (pixbuf != NULL) {
2372 priv->images_size += stream_size;
2373 priv->images_count ++;
2374 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2375 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2376 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2377 tny_mime_part_get_content_id (mime_part), pixbuf);
2378 g_object_unref (pixbuf);
2380 tny_list_prepend (priv->images, (GObject *) mime_part);
2381 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2383 modest_platform_information_banner (NULL, NULL,
2384 _("mail_ib_file_operation_failed"));
2388 g_object_unref (mime_part);
2389 gnome_vfs_file_info_unref (info);
2393 g_object_unref (window);
2397 on_attach_file_response (GtkDialog *dialog,
2401 GSList *uris = NULL;
2403 GnomeVFSFileSize total_size, allowed_size;
2404 ModestMsgEditWindow *window;
2405 ModestMsgEditWindowPrivate *priv;
2410 case GTK_RESPONSE_OK:
2412 gchar *current_folder;
2414 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2415 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2416 if (current_folder && current_folder != '\0') {
2418 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2419 current_folder, &err);
2421 g_debug ("Error storing latest used folder: %s", err->message);
2425 g_free (current_folder);
2432 window = MODEST_MSG_EDIT_WINDOW (user_data);
2433 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2435 /* allowed size is the maximum size - what's already there */
2436 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2437 &att_num, &att_size);
2438 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2441 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2443 const gchar *uri = (const gchar *) uri_node->data;
2446 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2448 if (total_size > allowed_size) {
2449 g_warning ("%s: total size: %u",
2450 __FUNCTION__, (unsigned int)total_size);
2453 allowed_size -= total_size;
2455 g_slist_foreach (uris, (GFunc) g_free, NULL);
2456 g_slist_free (uris);
2458 gtk_widget_destroy (GTK_WIDGET (dialog));
2462 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2464 GtkWidget *dialog = NULL;
2465 ModestMsgEditWindowPrivate *priv;
2468 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2470 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2472 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2475 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2476 GTK_FILE_CHOOSER_ACTION_OPEN);
2477 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2478 conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2479 if (conf_folder && conf_folder[0] != '\0') {
2480 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2483 /* Set the default folder to images folder */
2484 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2485 ".documents", NULL);
2486 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2487 g_free (docs_folder);
2489 g_free (conf_folder);
2490 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2491 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2492 GTK_WINDOW (dialog), GTK_WINDOW (window));
2494 /* Connect to response & show */
2495 g_signal_connect (dialog, "response",
2496 G_CALLBACK (on_attach_file_response), window);
2497 gtk_widget_show (dialog);
2502 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2504 GnomeVFSFileSize allowed_size)
2507 GnomeVFSHandle *handle = NULL;
2508 ModestMsgEditWindowPrivate *priv;
2509 GnomeVFSResult result;
2510 GnomeVFSFileSize size = 0;
2511 g_return_val_if_fail (window, 0);
2512 g_return_val_if_fail (uri, 0);
2514 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2516 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2517 if (result == GNOME_VFS_OK) {
2518 TnyMimePart *mime_part;
2520 const gchar *mime_type = NULL;
2522 gchar *escaped_filename;
2525 GnomeVFSFileInfo *info;
2526 GnomeVFSURI *vfs_uri;
2528 gnome_vfs_close (handle);
2529 vfs_uri = gnome_vfs_uri_new (uri);
2532 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2533 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2534 g_free (escaped_filename);
2535 gnome_vfs_uri_unref (vfs_uri);
2537 info = gnome_vfs_file_info_new ();
2539 if (gnome_vfs_get_file_info (uri,
2541 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2543 mime_type = gnome_vfs_file_info_get_mime_type (info);
2544 mime_part = tny_platform_factory_new_mime_part
2545 (modest_runtime_get_platform_factory ());
2547 /* try to get the attachment's size; this may fail for weird
2548 * file systems, like obex, upnp... */
2549 if (allowed_size != 0 &&
2550 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2552 if (size > allowed_size) {
2553 modest_platform_information_banner (NULL, NULL,
2554 _FM("sfil_ib_opening_not_allowed"));
2559 g_warning ("%s: could not get attachment size", __FUNCTION__);
2561 stream = create_stream_for_uri (uri);
2563 if (stream == NULL) {
2565 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2567 g_object_unref (mime_part);
2569 gnome_vfs_file_info_unref (info);
2573 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2574 g_object_unref (stream);
2576 content_id = g_strdup_printf ("%d", priv->next_cid);
2577 tny_mime_part_set_content_id (mime_part, content_id);
2578 g_free (content_id);
2581 basename = g_path_get_basename (filename);
2582 tny_mime_part_set_filename (mime_part, basename);
2585 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2586 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2588 info->size == 0, info->size);
2589 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2590 gtk_widget_show_all (priv->attachments_caption);
2591 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2593 g_object_unref (mime_part);
2594 gnome_vfs_file_info_unref (info);
2601 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2604 ModestMsgEditWindowPrivate *priv;
2607 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2608 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2610 if (att_list == NULL) {
2611 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2612 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2613 g_object_unref (att_list);
2618 g_object_ref (att_list);
2621 if (tny_list_get_length (att_list) == 0) {
2622 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2624 gboolean dialog_response;
2625 gchar *message = NULL;
2626 gchar *filename = NULL;
2628 if (tny_list_get_length (att_list) == 1) {
2630 iter = tny_list_create_iterator (att_list);
2631 part = (TnyMimePart *) tny_iterator_get_current (iter);
2632 g_object_unref (iter);
2633 if (TNY_IS_MSG (part)) {
2634 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2636 filename = tny_header_dup_subject (header);
2637 g_object_unref (header);
2639 if (filename == NULL) {
2640 filename = g_strdup (_("mail_va_no_subject"));
2643 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2645 g_object_unref (part);
2647 filename = g_strdup ("");
2649 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2650 "emev_nc_delete_attachments",
2651 tny_list_get_length (att_list)), filename);
2654 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2658 if (dialog_response != GTK_RESPONSE_OK) {
2659 g_object_unref (att_list);
2663 for (iter = tny_list_create_iterator (att_list);
2664 !tny_iterator_is_done (iter);
2665 tny_iterator_next (iter)) {
2666 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2667 const gchar *att_id;
2668 tny_list_remove (priv->attachments, (GObject *) mime_part);
2670 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2672 if (tny_list_get_length (priv->attachments) == 0)
2673 gtk_widget_hide (priv->attachments_caption);
2674 att_id = tny_mime_part_get_content_id (mime_part);
2676 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2678 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2679 g_object_unref (mime_part);
2681 g_object_unref (iter);
2684 g_object_unref (att_list);
2686 /* if the last attachment has been removed, focus the Subject: field */
2687 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2688 gtk_widget_grab_focus (priv->subject_field);
2692 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2695 ModestMsgEditWindowPrivate *priv;
2696 GdkColor *new_color;
2697 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2699 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2700 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2703 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2705 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2707 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2709 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2714 font_size_clicked (GtkToolButton *button,
2715 ModestMsgEditWindow *window)
2717 ModestMsgEditWindowPrivate *priv;
2718 GtkWidget *selector, *dialog;
2720 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2722 selector = hildon_touch_selector_new ();
2723 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2724 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2726 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2727 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2728 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2730 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2734 WPTextBufferFormat format;
2736 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2738 memset (&format, 0, sizeof (format));
2739 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2741 format.cs.font_size = TRUE;
2742 format.cs.text_position = TRUE;
2743 format.cs.font = TRUE;
2744 format.font_size = new_index;
2745 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2747 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2748 GINT_TO_POINTER (new_index)))
2749 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2751 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2752 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2753 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2754 size_text, "</span>", NULL);
2756 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2760 gtk_widget_destroy (dialog);
2762 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2767 font_face_clicked (GtkToolButton *button,
2768 ModestMsgEditWindow *window)
2770 ModestMsgEditWindowPrivate *priv;
2771 GtkWidget *selector, *dialog;
2772 GtkCellRenderer *renderer;
2774 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2776 selector = hildon_touch_selector_new ();
2777 renderer = gtk_cell_renderer_text_new ();
2778 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2779 renderer, "family", 0, "text", 0, NULL);
2780 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2782 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2783 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2784 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2786 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2787 gint new_font_index;
2791 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2792 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2793 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2797 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2799 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2800 GINT_TO_POINTER(new_font_index)))
2801 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2803 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2804 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2806 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2810 gtk_tree_path_free (path);
2813 gtk_widget_destroy (dialog);
2815 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2820 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2823 ModestMsgEditWindowPrivate *priv = NULL;
2824 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2826 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2827 if (!priv->update_caption_visibility)
2830 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2832 gtk_widget_show (priv->cc_caption);
2834 gtk_widget_hide (priv->cc_caption);
2836 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2840 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2843 ModestMsgEditWindowPrivate *priv = NULL;
2844 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2846 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2847 if (!priv->update_caption_visibility)
2850 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2852 gtk_widget_show (priv->bcc_caption);
2854 gtk_widget_hide (priv->bcc_caption);
2856 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2860 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2861 ModestRecptEditor *editor)
2863 ModestMsgEditWindowPrivate *priv;
2865 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2866 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2868 /* we check for low-mem; in that case, show a warning, and don't allow
2869 * for the addressbook
2871 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2874 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2876 if (editor == NULL) {
2877 GtkWidget *view_focus;
2878 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2880 /* This code should be kept in sync with ModestRecptEditor. The
2881 textview inside the recpt editor is the one that really gets the
2882 focus. As it's inside a scrolled window, and this one inside the
2883 hbox recpt editor inherits from, we'll need to go up in the
2884 hierarchy to know if the text view is part of the recpt editor
2885 or if it's a different text entry */
2887 if (gtk_widget_get_parent (view_focus)) {
2888 GtkWidget *first_parent;
2890 first_parent = gtk_widget_get_parent (view_focus);
2891 if (gtk_widget_get_parent (first_parent) &&
2892 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2893 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2898 editor = MODEST_RECPT_EDITOR (priv->to_field);
2902 modest_address_book_select_addresses (editor);
2907 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2909 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2911 modest_msg_edit_window_open_addressbook (window, NULL);
2915 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2916 gboolean show_toolbar)
2918 ModestWindowPrivate *parent_priv;
2920 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2921 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2923 /* We can not just use the code of
2924 modest_msg_edit_window_setup_toolbar because it has a
2925 mixture of both initialization and creation code. */
2927 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2929 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2933 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2934 TnyHeaderFlags priority_flags)
2936 ModestMsgEditWindowPrivate *priv;
2937 ModestWindowPrivate *parent_priv;
2939 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2941 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2942 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2944 if (priv->priority_flags != priority_flags) {
2945 GtkAction *priority_action = NULL;
2947 priv->priority_flags = priority_flags;
2949 switch (priority_flags) {
2950 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2951 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2952 MODEST_HEADER_ICON_HIGH,
2953 HILDON_ICON_SIZE_SMALL);
2954 gtk_widget_show (priv->priority_icon);
2955 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2956 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2958 case TNY_HEADER_FLAG_LOW_PRIORITY:
2959 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2960 MODEST_HEADER_ICON_LOW,
2961 HILDON_ICON_SIZE_SMALL);
2962 gtk_widget_show (priv->priority_icon);
2963 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2964 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2967 gtk_widget_hide (priv->priority_icon);
2968 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2969 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2972 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2973 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2975 gtk_widget_queue_resize (priv->subject_box);
2979 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2982 ModestMsgEditWindowPrivate *priv;
2983 ModestWindowPrivate *parent_priv;
2984 gint current_format;
2986 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2988 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2989 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2991 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2992 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2994 if (current_format != file_format) {
2995 switch (file_format) {
2996 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2997 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2998 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3000 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3004 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3005 response = gtk_dialog_run (GTK_DIALOG (dialog));
3006 gtk_widget_destroy (dialog);
3007 if (response == GTK_RESPONSE_OK) {
3008 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3010 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3011 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3016 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3017 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3018 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3023 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3026 ModestMsgEditWindowPrivate *priv;
3027 WPTextBufferFormat oldfmt, fmt;
3028 gint old_position = 0;
3032 GdkColor *color = NULL;
3033 gboolean bold, bold_set, italic, italic_set;
3034 gboolean underline, underline_set;
3035 gboolean strikethrough, strikethrough_set;
3036 gboolean position_set;
3037 gboolean font_size_set, font_set, color_set;
3040 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3041 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3043 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3044 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3045 GTK_WINDOW(dialog), GTK_WINDOW (window));
3047 /* First we get the currently selected font information */
3048 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3050 switch (oldfmt.text_position) {
3051 case TEXT_POSITION_NORMAL:
3054 case TEXT_POSITION_SUPERSCRIPT:
3062 g_object_set (G_OBJECT (dialog),
3063 "bold", oldfmt.bold != FALSE,
3064 "bold-set", !oldfmt.cs.bold,
3065 "underline", oldfmt.underline != FALSE,
3066 "underline-set", !oldfmt.cs.underline,
3067 "italic", oldfmt.italic != FALSE,
3068 "italic-set", !oldfmt.cs.italic,
3069 "strikethrough", oldfmt.strikethrough != FALSE,
3070 "strikethrough-set", !oldfmt.cs.strikethrough,
3071 "color", &oldfmt.color,
3072 "color-set", !oldfmt.cs.color,
3073 "size", wp_font_size[oldfmt.font_size],
3074 "size-set", !oldfmt.cs.font_size,
3075 "position", old_position,
3076 "position-set", !oldfmt.cs.text_position,
3077 "family", wp_get_font_name (oldfmt.font),
3078 "family-set", !oldfmt.cs.font,
3081 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3082 GTK_WINDOW (dialog), GTK_WINDOW (window));
3083 gtk_widget_show_all (dialog);
3084 priv->font_dialog = dialog;
3085 response = gtk_dialog_run (GTK_DIALOG (dialog));
3086 priv->font_dialog = NULL;
3087 if (response == GTK_RESPONSE_OK) {
3089 g_object_get( dialog,
3091 "bold-set", &bold_set,
3092 "underline", &underline,
3093 "underline-set", &underline_set,
3095 "italic-set", &italic_set,
3096 "strikethrough", &strikethrough,
3097 "strikethrough-set", &strikethrough_set,
3099 "color-set", &color_set,
3101 "size-set", &font_size_set,
3102 "family", &font_name,
3103 "family-set", &font_set,
3104 "position", &position,
3105 "position-set", &position_set,
3110 if (response == GTK_RESPONSE_OK) {
3111 memset(&fmt, 0, sizeof(fmt));
3117 fmt.italic = italic;
3118 fmt.cs.italic = TRUE;
3120 if (underline_set) {
3121 fmt.underline = underline;
3122 fmt.cs.underline = TRUE;
3124 if (strikethrough_set) {
3125 fmt.strikethrough = strikethrough;
3126 fmt.cs.strikethrough = TRUE;
3131 ? TEXT_POSITION_NORMAL
3132 : ( ( position == 1 )
3133 ? TEXT_POSITION_SUPERSCRIPT
3134 : TEXT_POSITION_SUBSCRIPT );
3135 fmt.cs.text_position = TRUE;
3136 fmt.font_size = oldfmt.font_size;
3140 fmt.cs.color = TRUE;
3143 fmt.font = wp_get_font_index(font_name,
3148 if (font_size_set) {
3149 fmt.cs.font_size = TRUE;
3150 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3152 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3153 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3155 gtk_widget_destroy (dialog);
3157 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3161 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3163 ModestMsgEditWindowPrivate *priv;
3165 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3166 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3168 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3170 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3171 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3175 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3177 ModestMsgEditWindowPrivate *priv;
3179 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3180 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3182 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3184 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3185 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3190 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3192 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3194 priv->can_undo = can_undo;
3198 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3200 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3202 priv->can_redo = can_redo;
3206 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3208 ModestMsgEditWindowPrivate *priv;
3209 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3210 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3212 return priv->can_undo;
3216 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3218 ModestMsgEditWindowPrivate *priv;
3219 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3220 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3222 return priv->can_redo;
3227 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3230 GtkTextIter match_start, match_end;
3232 if (image_id == NULL)
3235 gtk_text_buffer_get_start_iter (buffer, &iter);
3237 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3238 GSList *tags = gtk_text_iter_get_tags (&match_start);
3240 for (node = tags; node != NULL; node = g_slist_next (node)) {
3241 GtkTextTag *tag = (GtkTextTag *) node->data;
3242 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3243 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3244 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3246 offset = gtk_text_iter_get_offset (&match_start);
3247 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3248 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3252 gtk_text_iter_forward_char (&iter);
3257 message_is_empty (ModestMsgEditWindow *window)
3259 ModestMsgEditWindowPrivate *priv = NULL;
3261 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3262 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3264 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3265 * so we can ignore markup.
3267 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3270 count = gtk_text_buffer_get_char_count (buf);
3276 msg_body_focus (GtkWidget *focus,
3277 GdkEventFocus *event,
3281 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3282 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3283 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3288 recpt_field_changed (GtkTextBuffer *buffer,
3289 ModestMsgEditWindow *editor)
3291 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3292 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3296 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3298 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3299 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3303 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3306 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3307 GtkTextBuffer *buffer;
3309 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3310 gtk_text_buffer_set_modified (buffer, modified);
3311 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3312 gtk_text_buffer_set_modified (buffer, modified);
3313 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3314 gtk_text_buffer_set_modified (buffer, modified);
3315 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3319 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3321 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3322 const char *account_name;
3323 GtkTextBuffer *buffer;
3325 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3326 if (gtk_text_buffer_get_modified (buffer))
3328 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3329 if (gtk_text_buffer_get_modified (buffer))
3331 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3332 if (gtk_text_buffer_get_modified (buffer))
3334 if (gtk_text_buffer_get_modified (priv->text_buffer))
3337 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3338 if (priv->original_mailbox) {
3339 if (!account_name || strcmp (account_name, priv->original_mailbox))
3341 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3352 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3354 ModestMsgEditWindowPrivate *priv = NULL;
3356 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3357 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3359 /* check if there's no recipient added */
3360 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3361 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3362 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3363 /* no recipient contents, then select contacts */
3364 modest_msg_edit_window_open_addressbook (window, NULL);
3368 g_object_ref (window);
3369 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3370 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3371 g_object_unref (window);
3374 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3375 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3376 g_object_unref (window);
3379 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3380 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3381 g_object_unref (window);
3385 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3386 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3387 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3388 g_object_unref (window);
3395 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3396 ModestMsgEditWindow *window)
3398 modest_msg_edit_window_offer_attach_file (window);
3402 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3404 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3406 return priv->clipboard_text;
3410 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3412 ModestMsgEditWindow *window)
3414 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3415 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3418 /* It could happen that the window was already closed */
3419 if (!GTK_WIDGET_VISIBLE (window))
3422 g_object_ref (window);
3423 text = gtk_clipboard_wait_for_text (selection_clipboard);
3425 if (priv->clipboard_text != NULL) {
3426 g_free (priv->clipboard_text);
3428 priv->clipboard_text = text;
3430 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3432 g_object_unref (window);
3435 static gboolean clipboard_owner_change_idle (gpointer userdata)
3437 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3438 ModestMsgEditWindowPrivate *priv;
3440 gdk_threads_enter ();
3441 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3442 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3444 priv->clipboard_owner_idle = 0;
3445 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3446 gdk_threads_leave ();
3452 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3454 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3455 if (priv->clipboard_owner_idle == 0) {
3456 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3457 clipboard_owner_change_idle,
3458 g_object_ref (window),
3464 subject_field_move_cursor (GtkEntry *entry,
3465 GtkMovementStep step,
3470 /* It could happen that the window was already closed */
3471 if (!GTK_WIDGET_VISIBLE (window))
3474 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3478 update_window_title (ModestMsgEditWindow *window)
3480 ModestMsgEditWindowPrivate *priv = NULL;
3481 const gchar *subject;
3483 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3484 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3485 if (subject == NULL || subject[0] == '\0')
3486 subject = _("mail_va_new_email");
3488 gtk_window_set_title (GTK_WINDOW (window), subject);
3493 subject_field_changed (GtkEditable *editable,
3494 ModestMsgEditWindow *window)
3496 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3497 update_window_title (window);
3498 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3499 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3500 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3504 subject_field_insert_text (GtkEditable *editable,
3506 gint new_text_length,
3508 ModestMsgEditWindow *window)
3510 GString *result = g_string_new ("");
3512 gint result_len = 0;
3513 const gchar *entry_text = NULL;
3516 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3517 old_length = g_utf8_strlen (entry_text, -1);
3519 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3520 gunichar c = g_utf8_get_char_validated (current, 8);
3521 /* Invalid unichar, stop */
3527 result = g_string_append_unichar (result, c);
3531 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3532 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3535 /* Prevent endless recursion */
3536 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3537 g_signal_emit_by_name (editable, "insert-text",
3538 (gpointer) result->str, (gpointer) result->len,
3539 (gpointer) position, (gpointer) window);
3540 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3544 if (result_len + old_length > 1000) {
3545 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3546 _CS("ckdg_ib_maximum_characters_reached"));
3548 g_string_free (result, TRUE);
3552 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3555 ModestMsgEditWindowPrivate *priv = NULL;
3557 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3558 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3560 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3563 gtk_widget_show_all (priv->find_toolbar);
3564 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3566 gtk_widget_hide_all (priv->find_toolbar);
3567 gtk_widget_grab_focus (priv->msg_body);
3572 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3574 GtkTextIter *match_start,
3575 GtkTextIter *match_end)
3577 GtkTextIter end_iter;
3578 gchar *str_casefold;
3581 gchar *range_casefold;
3584 gboolean result = FALSE;
3591 gtk_text_iter_forward_to_end (&end_iter);
3593 str_casefold = g_utf8_casefold (str, -1);
3594 str_chars_n = strlen (str);
3596 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3597 range_casefold = g_utf8_casefold (range_text, -1);
3598 range_chars_n = strlen (range_casefold);
3600 if (range_chars_n < str_chars_n) {
3601 g_free (str_casefold);
3602 g_free (range_text);
3603 g_free (range_casefold);
3607 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3608 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3609 if (!g_utf8_collate (range_subtext, str_casefold)) {
3610 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3612 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3613 match_start, match_end, NULL)) {
3614 g_warning ("Matched string with collate, but not matched in model");
3616 g_free (found_text);
3618 g_free (range_subtext);
3622 g_free (str_casefold);
3623 g_free (range_text);
3624 g_free (range_casefold);
3631 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3632 ModestMsgEditWindow *window)
3634 gchar *current_search = NULL;
3635 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3637 GtkTextIter selection_start, selection_end;
3638 GtkTextIter match_start, match_end;
3639 gboolean continue_search = FALSE;
3641 if (message_is_empty (window)) {
3642 g_free (priv->last_search);
3643 priv->last_search = NULL;
3644 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3648 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3649 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3650 g_free (current_search);
3651 g_free (priv->last_search);
3652 priv->last_search = NULL;
3653 /* Information banner about empty search */
3654 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3658 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3659 continue_search = TRUE;
3661 g_free (priv->last_search);
3662 priv->last_search = g_strdup (current_search);
3665 if (continue_search) {
3666 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3667 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3668 &match_start, &match_end);
3670 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3672 GtkTextIter buffer_start;
3673 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3674 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3675 &match_start, &match_end);
3677 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3680 /* Mark as selected the string found in search */
3682 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3683 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3684 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3686 g_free (priv->last_search);
3687 priv->last_search = NULL;
3689 g_free (current_search);
3693 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3695 ModestMsgEditWindowPrivate *priv;
3697 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3702 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3705 ModestMsgEditWindowPrivate *priv;
3707 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3712 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3713 ModestMsgEditWindow *window)
3715 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3719 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3722 ModestMsgEditWindowPrivate *priv;
3723 TnyHeader *header = NULL;
3725 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3726 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3728 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3730 if (priv->draft_msg != NULL) {
3731 g_object_unref (priv->draft_msg);
3734 if (draft != NULL) {
3735 g_object_ref (draft);
3736 header = tny_msg_get_header (draft);
3737 if (priv->msg_uid) {
3738 g_free (priv->msg_uid);
3739 priv->msg_uid = NULL;
3741 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3744 priv->draft_msg = draft;
3748 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3749 GtkTextIter *start, GtkTextIter *end,
3752 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3753 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3756 if (tag == NULL) return;
3757 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3758 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3759 replace_with_images (window, priv->images);
3764 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3767 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3769 g_return_if_fail (TNY_IS_MIME_PART (part));
3770 tny_list_prepend (priv->attachments, (GObject *) part);
3771 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3772 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3773 gtk_widget_show_all (priv->attachments_caption);
3774 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3778 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3780 ModestMsgEditWindowPrivate *priv;
3782 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3783 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3785 return priv->msg_uid;
3789 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3790 ModestMsgEditWindowWidgetType widget_type)
3792 ModestMsgEditWindowPrivate *priv;
3794 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3795 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3797 switch (widget_type) {
3798 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3799 return priv->msg_body;
3801 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3802 return priv->to_field;
3804 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3805 return priv->cc_field;
3807 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3808 return priv->bcc_field;
3810 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3811 return priv->subject_field;
3813 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3814 return priv->attachments_view;
3822 remove_tags (WPTextBuffer *buffer)
3824 GtkTextIter start, end;
3826 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3827 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3829 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3833 on_account_removed (TnyAccountStore *account_store,
3834 TnyAccount *account,
3837 /* Do nothing if it's a store account, because we use the
3838 transport to send the messages */
3839 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3840 const gchar *parent_acc = NULL;
3841 const gchar *our_acc = NULL;
3843 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3844 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3845 /* Close this window if I'm showing a message of the removed account */
3846 if (strcmp (parent_acc, our_acc) == 0)
3847 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3851 static void update_signature (ModestMsgEditWindow *self,
3852 const gchar *old_account,
3853 const gchar *new_account)
3855 ModestMsgEditWindowPrivate *priv;
3856 gboolean has_old_signature, has_new_signature;
3858 GtkTextIter match_start, match_end;
3859 ModestAccountMgr *mgr;
3861 gchar *full_signature;
3863 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3865 gtk_text_buffer_begin_user_action (priv->text_buffer);
3867 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3868 mgr = modest_runtime_get_account_mgr ();
3872 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
3873 if (has_old_signature) {
3874 full_signature = g_strconcat ("\n--\n", signature, NULL);
3875 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3876 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3878 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3879 &match_start, &match_end, NULL)) {
3882 g_free (full_signature);
3887 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3888 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
3889 if (has_new_signature) {
3890 full_signature = g_strconcat ("\n--\n", signature, NULL);
3891 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3892 g_free (full_signature);
3895 gtk_text_buffer_end_user_action (priv->text_buffer);
3899 from_field_changed (HildonPickerButton *button,
3900 ModestMsgEditWindow *self)
3902 ModestMsgEditWindowPrivate *priv;
3903 gchar *old_account, *new_account;
3905 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3907 old_account = priv->last_from_account;
3908 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3909 new_account = priv->last_from_account;
3911 update_signature (self, old_account, new_account);
3915 typedef struct _MessageSettingsHelper {
3916 ModestMsgEditWindow *window;
3917 GSList *priority_group;
3918 GSList *format_group;
3919 GtkToggleButton *current_priority;
3920 GtkToggleButton *current_format;
3921 } MessageSettingsHelper;
3924 on_priority_toggle (GtkToggleButton *button,
3925 MessageSettingsHelper *helper)
3928 ModestMsgEditWindowPrivate *priv;
3930 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3931 if (gtk_toggle_button_get_active (button)) {
3933 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3934 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3935 if ((node_button != button) &&
3936 gtk_toggle_button_get_active (node_button)) {
3937 gtk_toggle_button_set_active (node_button, FALSE);
3940 helper->current_priority = button;
3942 gboolean found = FALSE;
3943 /* If no one is active, activate it again */
3944 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3945 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3946 if (gtk_toggle_button_get_active (node_button)) {
3952 gtk_toggle_button_set_active (button, TRUE);
3958 on_format_toggle (GtkToggleButton *button,
3959 MessageSettingsHelper *helper)
3962 ModestMsgEditWindowPrivate *priv;
3964 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3965 if (gtk_toggle_button_get_active (button)) {
3967 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3968 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3969 if ((node_button != button) &&
3970 gtk_toggle_button_get_active (node_button)) {
3971 gtk_toggle_button_set_active (node_button, FALSE);
3974 helper->current_format = button;
3976 gboolean found = FALSE;
3977 /* If no one is active, activate it again */
3978 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3979 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3980 if (gtk_toggle_button_get_active (node_button)) {
3986 gtk_toggle_button_set_active (button, TRUE);
3993 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3998 GtkWidget *priority_hbox;
3999 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4000 GtkWidget *captioned;
4001 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4002 GtkWidget *format_hbox;
4003 GtkWidget *html_toggle, *text_toggle;
4004 ModestMsgEditWindowPrivate *priv;
4005 MessageSettingsHelper helper = {0,};
4007 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4008 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4009 helper.window = window;
4010 helper.priority_group = NULL;
4011 helper.format_group = NULL;
4013 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4014 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4016 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4017 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4018 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4019 vbox = gtk_vbox_new (FALSE, 0);
4020 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4021 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4022 gtk_container_add (GTK_CONTAINER (align), vbox);
4023 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4024 gtk_widget_show (align);
4025 gtk_widget_show (vbox);
4027 /* Priority toggles */
4028 priority_hbox = gtk_hbox_new (TRUE, 0);
4029 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4030 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4031 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4032 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4033 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4034 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4035 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4036 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4037 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4038 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4039 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4040 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4041 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4042 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4043 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4044 gtk_widget_show_all (priority_hbox);
4045 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4046 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4047 gtk_widget_show (captioned);
4048 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4050 /* format toggles */
4051 format_hbox = gtk_hbox_new (TRUE, 0);
4052 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4053 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4054 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4055 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4056 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4057 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4058 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4059 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4060 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4061 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4062 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4063 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4064 gtk_widget_show_all (format_hbox);
4065 gtk_widget_show (format_hbox);
4066 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4069 g_object_unref (title_sizegroup);
4070 g_object_unref (value_sizegroup);
4072 /* Set current values */
4073 switch (priv->priority_flags) {
4074 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4075 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4076 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4078 case TNY_HEADER_FLAG_LOW_PRIORITY:
4079 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4080 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4083 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4084 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4088 switch (modest_msg_edit_window_get_format (window)) {
4089 case MODEST_MSG_EDIT_FORMAT_TEXT:
4090 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4091 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4093 case MODEST_MSG_EDIT_FORMAT_HTML:
4095 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4096 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4100 /* Signal connects */
4101 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4102 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4103 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4104 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4105 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4107 /* Save settings if the user clicked on done */
4108 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4109 TnyHeaderFlags flags;
4110 ModestMsgEditFormat old_format, new_format;
4112 /* Set priority flags */
4113 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4114 if (priv->priority_flags != flags)
4115 modest_msg_edit_window_set_priority_flags (window, flags);
4117 /* Set edit format */
4118 old_format = modest_msg_edit_window_get_format (window);
4119 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4120 if (old_format != new_format) {
4121 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4122 modest_msg_edit_window_set_file_format (window, file_format);
4126 gtk_widget_destroy (dialog);
4127 g_slist_free (helper.priority_group);
4131 on_message_settings (GtkAction *action,
4132 ModestMsgEditWindow *window)
4134 modest_msg_edit_window_show_msg_settings_dialog (window);
4138 on_cc_button_toggled (HildonCheckButton *button,
4139 ModestMsgEditWindow *window)
4141 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4143 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4144 hildon_check_button_get_active (button));
4148 on_bcc_button_toggled (HildonCheckButton *button,
4149 ModestMsgEditWindow *window)
4151 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4153 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4154 hildon_check_button_get_active (button));
4158 setup_menu (ModestMsgEditWindow *self)
4160 ModestMsgEditWindowPrivate *priv = NULL;
4162 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4164 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4166 /* Settings menu buttons */
4167 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4168 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4170 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4171 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4172 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4174 priv->cc_button = hildon_check_button_new (0);
4175 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4176 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4178 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4180 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4181 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4182 priv->bcc_button = hildon_check_button_new (0);
4183 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4184 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4186 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4188 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4189 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4191 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4192 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4193 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4194 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4195 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4196 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4197 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4198 APP_MENU_CALLBACK (on_message_settings),
4200 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4201 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),