1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
39 #include <modest-account-protocol.h>
43 #include <modest-account-mgr.h>
44 #include <modest-account-mgr-helpers.h>
46 #include <widgets/modest-msg-edit-window.h>
47 #include <modest-selector-picker.h>
48 #include <widgets/modest-recpt-editor.h>
49 #include <widgets/modest-attachments-view.h>
51 #include <modest-runtime.h>
53 #include "modest-platform.h"
54 #include "modest-icon-names.h"
55 #include "modest-widget-memory.h"
56 #include "modest-window-priv.h"
57 #include "modest-mail-operation.h"
58 #include "modest-tny-platform-factory.h"
59 #include "modest-tny-msg.h"
60 #include "modest-tny-folder.h"
61 #include "modest-tny-account.h"
62 #include "modest-address-book.h"
63 #include "modest-text-utils.h"
64 #include <tny-simple-list.h>
65 #include <modest-wp-text-view.h>
66 #include <wptextbuffer.h>
67 #include <hildon/hildon-pannable-area.h>
68 #include <hildon/hildon-touch-selector.h>
69 #include <hildon/hildon-picker-dialog.h>
70 #include "modest-msg-edit-window-ui-dimming.h"
72 #include "modest-hildon-includes.h"
73 #ifdef MODEST_HAVE_HILDON0_WIDGETS
74 #include <hildon-widgets/hildon-color-chooser.h>
76 #include "widgets/modest-msg-edit-window-ui.h"
77 #ifdef MODEST_HAVE_HILDON0_WIDGETS
78 #include <libgnomevfs/gnome-vfs-mime-utils.h>
80 #include <libgnomevfs/gnome-vfs-mime.h>
82 #include <modest-utils.h>
83 #include "modest-maemo-utils.h"
84 #include <modest-ui-constants.h>
87 #define DEFAULT_FONT_SIZE 3
88 #define DEFAULT_FONT 2
89 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
90 #define DEFAULT_MAIN_VBOX_SPACING 6
91 #define SUBJECT_MAX_LENGTH 1000
92 #define IMAGE_MAX_WIDTH 560
93 #define DEFAULT_FONT_SCALE 1.5
94 #define ATTACHMENT_BUTTON_WIDTH 118
95 #define MAX_FROM_VALUE 36
96 #define MAX_BODY_LENGTH 4096
98 static gboolean is_wp_text_buffer_started = FALSE;
100 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
101 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
102 static void modest_msg_edit_window_finalize (GObject *obj);
104 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
105 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
106 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
108 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
109 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
110 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
111 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
112 GtkTextIter *start, GtkTextIter *end,
114 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
115 static void body_insert_text (GtkTextBuffer *buffer,
116 GtkTextIter *location,
119 ModestMsgEditWindow *window);
120 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
121 static void subject_field_insert_text (GtkEditable *editable,
123 gint new_text_length,
125 ModestMsgEditWindow *window);
126 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
128 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
130 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
131 ModestRecptEditor *editor);
132 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
133 ModestMsgEditWindow *window);
135 /* ModestWindow methods implementation */
136 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
137 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
138 gboolean show_toolbar);
139 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
141 ModestMsgEditWindow *window);
142 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
143 static void subject_field_move_cursor (GtkEntry *entry,
144 GtkMovementStep step,
148 static void update_window_title (ModestMsgEditWindow *window);
151 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
152 ModestMsgEditWindow *window);
153 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
154 ModestMsgEditWindow *window);
155 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
157 GtkTextIter *match_start,
158 GtkTextIter *match_end);
160 static void remove_tags (WPTextBuffer *buffer);
162 static void on_account_removed (TnyAccountStore *account_store,
166 static void init_window (ModestMsgEditWindow *obj);
168 gboolean scroll_drag_timeout (gpointer userdata);
169 static void correct_scroll (ModestMsgEditWindow *w);
170 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
171 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
172 ModestMsgEditWindow *userdata);
173 static void text_buffer_mark_set (GtkTextBuffer *buffer,
176 ModestMsgEditWindow *userdata);
177 static void on_message_settings (GtkAction *action,
178 ModestMsgEditWindow *window);
179 static void setup_menu (ModestMsgEditWindow *self);
181 static void from_field_changed (HildonPickerButton *button,
182 ModestMsgEditWindow *self);
183 static void font_size_clicked (GtkToolButton *button,
184 ModestMsgEditWindow *window);
185 static void font_face_clicked (GtkToolButton *button,
186 ModestMsgEditWindow *window);
187 static void update_signature (ModestMsgEditWindow *self,
188 const gchar *old_account,
189 const gchar *new_account);
190 static GtkWidget *_create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
191 const gchar *label, GtkWidget *control);
192 static void DEBUG_BUFFER (WPTextBuffer *buffer)
196 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
198 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
199 while (!gtk_text_iter_is_end (&iter)) {
200 GString *output = g_string_new ("");
201 GSList *toggled_tags;
204 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
205 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
206 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
207 GtkTextTag *tag = (GtkTextTag *) node->data;
209 g_object_get (G_OBJECT (tag), "name", &name, NULL);
210 output = g_string_append (output, name);
211 g_string_append (output, " ");
213 output = g_string_append (output, "] OPENED [ ");
214 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
215 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
216 GtkTextTag *tag = (GtkTextTag *) node->data;
218 g_object_get (G_OBJECT (tag), "name", &name, NULL);
219 output = g_string_append (output, name);
220 g_string_append (output, " ");
222 output = g_string_append (output, "]\n");
223 g_message ("%s", output->str);
224 g_string_free (output, TRUE);
225 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
227 g_message ("END BUFFER");
231 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
232 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
236 /* static gboolean */
237 /* on_key_pressed (GtkWidget *self, */
238 /* GdkEventKey *event, */
239 /* gpointer user_data); */
241 /* list my signals */
248 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
249 struct _ModestMsgEditWindowPrivate {
251 GtkWidget *header_box;
253 ModestPairList *from_field_protos;
254 GtkWidget *from_field;
255 gchar *last_from_account;
256 gchar *original_account_name;
261 gchar *original_mailbox;
265 GtkWidget *bcc_field;
266 GtkWidget *subject_field;
267 GtkWidget *attachments_view;
268 GtkWidget *priority_icon;
269 GtkWidget *subject_box;
270 GtkWidget *send_button;
272 GtkWidget *cc_caption;
273 GtkWidget *bcc_caption;
274 gboolean update_caption_visibility;
275 GtkWidget *attachments_caption;
277 GtkTextBuffer *text_buffer;
279 GtkWidget *font_size_toolitem;
280 GtkWidget *font_face_toolitem;
281 GtkWidget *font_color_button;
282 GtkWidget *font_color_toolitem;
283 GSList *font_items_group;
284 GtkTreeModel *faces_model;
285 gint current_face_index;
286 GtkWidget *font_tool_button_label;
287 GtkTreeModel *sizes_model;
288 gint current_size_index;
289 GtkWidget *size_tool_button_label;
291 GtkWidget *find_toolbar;
294 GtkWidget *font_dialog;
297 guint correct_scroll_idle;
298 guint scroll_drag_timeout_id;
302 TnyList *attachments;
307 TnyHeaderFlags priority_flags;
309 gboolean can_undo, can_redo;
310 gulong clipboard_change_handler_id;
311 gulong default_clipboard_change_handler_id;
312 gulong account_removed_handler_id;
313 guint clipboard_owner_idle;
314 gchar *clipboard_text;
323 GtkWidget *cc_button;
324 GtkWidget *bcc_button;
327 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
328 MODEST_TYPE_MSG_EDIT_WINDOW, \
329 ModestMsgEditWindowPrivate))
331 static GtkWindowClass *parent_class = NULL;
333 /* uncomment the following if you have defined any signals */
334 /* static guint signals[LAST_SIGNAL] = {0}; */
337 modest_msg_edit_window_get_type (void)
339 static GType my_type = 0;
341 static const GTypeInfo my_info = {
342 sizeof(ModestMsgEditWindowClass),
343 NULL, /* base init */
344 NULL, /* base finalize */
345 (GClassInitFunc) modest_msg_edit_window_class_init,
346 NULL, /* class finalize */
347 NULL, /* class data */
348 sizeof(ModestMsgEditWindow),
350 (GInstanceInitFunc) modest_msg_edit_window_init,
353 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
354 "ModestMsgEditWindow",
362 save_state (ModestWindow *self)
364 modest_widget_memory_save (modest_runtime_get_conf(),
365 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
370 restore_settings (ModestMsgEditWindow *self)
372 ModestConf *conf = NULL;
374 conf = modest_runtime_get_conf ();
376 /* Dim at start clipboard actions */
377 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
382 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
384 GObjectClass *gobject_class;
385 ModestWindowClass *modest_window_class;
386 gobject_class = (GObjectClass*) klass;
387 modest_window_class = (ModestWindowClass*) klass;
389 parent_class = g_type_class_peek_parent (klass);
390 gobject_class->finalize = modest_msg_edit_window_finalize;
392 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
393 modest_window_class->save_state_func = save_state;
394 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
396 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
400 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
402 ModestMsgEditWindowPrivate *priv;
403 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
405 priv->msg_body = NULL;
406 priv->from_field = NULL;
407 priv->to_field = NULL;
408 priv->cc_field = NULL;
409 priv->bcc_field = NULL;
410 priv->subject_field = NULL;
411 priv->attachments = TNY_LIST (tny_simple_list_new ());
412 priv->images = TNY_LIST (tny_simple_list_new ());
413 priv->images_size = 0;
414 priv->images_count = 0;
417 priv->cc_caption = NULL;
418 priv->bcc_caption = NULL;
419 priv->update_caption_visibility = FALSE;
421 priv->priority_flags = 0;
423 priv->find_toolbar = NULL;
424 priv->last_search = NULL;
426 priv->draft_msg = NULL;
427 priv->outbox_msg = NULL;
428 priv->msg_uid = NULL;
430 priv->can_undo = FALSE;
431 priv->can_redo = FALSE;
432 priv->clipboard_change_handler_id = 0;
433 priv->default_clipboard_change_handler_id = 0;
434 priv->account_removed_handler_id = 0;
435 priv->clipboard_owner_idle = 0;
436 priv->clipboard_text = NULL;
439 priv->scroll_drag_timeout_id = 0;
440 priv->correct_scroll_idle = 0;
441 priv->last_upper = 0.0;
443 priv->font_dialog = NULL;
444 priv->app_menu = NULL;
446 priv->references = NULL;
447 priv->in_reply_to = NULL;
449 if (!is_wp_text_buffer_started) {
450 is_wp_text_buffer_started = TRUE;
451 wp_text_buffer_library_init ();
456 hildon_program_add_window (hildon_program_get_instance(),
461 multimailbox_get_default_mailbox (const gchar *account_name)
463 gchar *transport_account;
464 gchar *result = NULL;
466 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
468 TNY_ACCOUNT_TYPE_TRANSPORT);
469 if (transport_account) {
471 ModestProtocolRegistry *registry;
473 registry = modest_runtime_get_protocol_registry ();
475 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
476 MODEST_ACCOUNT_PROTO, TRUE);
478 ModestProtocol *protocol =
479 modest_protocol_registry_get_protocol_by_name (registry,
480 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
482 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
483 ModestPairList *pair_list;
485 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
488 ModestPair *pair = (ModestPair *) pair_list->data;
489 result = g_strdup ((const gchar *) pair->first);
490 modest_pair_list_free (pair_list);
501 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
503 static ModestPairList*
504 get_transports (void)
506 GSList *transports = NULL;
508 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
509 GSList *accounts = modest_account_mgr_account_names (account_mgr,
510 TRUE /* only enabled accounts. */);
512 GSList *cursor = accounts;
514 gchar *account_name = cursor->data;
517 gchar *transport_account;
518 gboolean multi_mailbox = FALSE;
519 ModestProtocol *protocol = NULL;
521 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
523 transport_account = modest_account_mgr_get_server_account_name
524 (modest_runtime_get_account_mgr (),
526 TNY_ACCOUNT_TYPE_TRANSPORT);
527 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
528 ModestPairList *pair_list;
529 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
532 transports = g_slist_concat (transports, pair_list);
533 multi_mailbox = TRUE;
538 if (!multi_mailbox) {
539 gchar *from_string = NULL;
541 from_string = modest_account_mgr_get_from_string (account_mgr,
543 if (from_string && account_name) {
544 gchar *name = account_name;
545 ModestPair *pair = modest_pair_new ((gpointer) name,
546 (gpointer) from_string , TRUE);
547 transports = g_slist_prepend (transports, pair);
552 cursor = cursor->next;
554 g_slist_free (accounts); /* only free the accounts, not the elements,
555 * because they are used in the pairlist */
559 static void window_focus (GtkWindow *window,
563 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
567 scroll_drag_timeout (gpointer userdata)
569 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
570 ModestMsgEditWindowPrivate *priv;
572 /* It could happen that the window was already closed */
573 if (!GTK_WIDGET_VISIBLE (win))
576 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
578 correct_scroll_without_drag_check (win, TRUE);
580 priv->scroll_drag_timeout_id = 0;
586 correct_scroll_without_drag_check_idle (gpointer userdata)
588 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
589 ModestMsgEditWindowPrivate *priv;
591 GdkRectangle rectangle;
592 gint offset_min, offset_max;
596 /* It could happen that the window was already closed */
597 if (!GTK_WIDGET_VISIBLE (w))
600 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
602 insert = gtk_text_buffer_get_insert (priv->text_buffer);
603 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
605 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
606 offset_min = priv->msg_body->allocation.y + rectangle.y;
607 offset_max = offset_min + rectangle.height;
609 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
610 offset_min = MAX (offset_min - 48, 0);
611 offset_max = MIN (offset_max + 48, vadj->upper);
613 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
615 priv->correct_scroll_idle = 0;
620 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
622 ModestMsgEditWindowPrivate *priv;
624 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
626 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
629 if (priv->correct_scroll_idle > 0) {
633 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
634 (GSourceFunc) correct_scroll_without_drag_check_idle,
640 correct_scroll (ModestMsgEditWindow *w)
642 ModestMsgEditWindowPrivate *priv;
644 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
645 if (gtk_grab_get_current () == priv->msg_body) {
646 if (priv->scroll_drag_timeout_id == 0) {
647 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
649 (GSourceFunc) scroll_drag_timeout,
656 correct_scroll_without_drag_check (w, TRUE);
660 text_buffer_end_user_action (GtkTextBuffer *buffer,
661 ModestMsgEditWindow *userdata)
664 correct_scroll (userdata);
668 text_buffer_mark_set (GtkTextBuffer *buffer,
671 ModestMsgEditWindow *userdata)
673 gtk_text_buffer_begin_user_action (buffer);
674 gtk_text_buffer_end_user_action (buffer);
678 cut_clipboard_check (GtkTextView *text_view,
681 GtkTextBuffer *buffer;
683 buffer = gtk_text_view_get_buffer (text_view);
684 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
685 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
690 copy_clipboard_check (GtkTextView *text_view,
693 GtkTextBuffer *buffer;
695 buffer = gtk_text_view_get_buffer (text_view);
696 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
697 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
702 attachment_deleted (ModestAttachmentsView *attachments_view,
705 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
710 connect_signals (ModestMsgEditWindow *obj)
712 ModestMsgEditWindowPrivate *priv;
714 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
716 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
717 G_CALLBACK (text_buffer_refresh_attributes), obj);
718 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
719 G_CALLBACK (text_buffer_can_undo), obj);
720 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
721 G_CALLBACK (text_buffer_can_redo), obj);
722 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
723 G_CALLBACK (body_changed), obj);
724 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
725 G_CALLBACK (body_insert_text), obj);
726 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
727 G_CALLBACK (body_changed), obj);
728 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
729 G_CALLBACK (text_buffer_end_user_action), obj);
730 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
731 G_CALLBACK (text_buffer_mark_set), obj);
732 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
733 G_CALLBACK (text_buffer_apply_tag), obj);
734 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
735 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
736 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
737 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
738 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
739 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
741 g_signal_connect (G_OBJECT (priv->send_button), "clicked",
742 G_CALLBACK (modest_ui_actions_on_send), obj);
744 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
745 G_CALLBACK (from_field_changed), obj);
747 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
748 G_CALLBACK (msg_body_focus), obj);
749 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
750 G_CALLBACK (msg_body_focus), obj);
751 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
752 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
753 "changed", G_CALLBACK (recpt_field_changed), obj);
754 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
755 "changed", G_CALLBACK (recpt_field_changed), obj);
756 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
757 "changed", G_CALLBACK (recpt_field_changed), obj);
758 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
759 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
760 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
762 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
763 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
765 priv->clipboard_change_handler_id =
766 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
767 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
768 priv->default_clipboard_change_handler_id =
769 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
770 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
772 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
773 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
774 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
778 init_wp_text_view_style ()
780 static gboolean initialized = FALSE;
783 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
789 init_window (ModestMsgEditWindow *obj)
791 GtkWidget *to_caption, *subject_caption;
792 GtkWidget *main_vbox;
793 ModestMsgEditWindowPrivate *priv;
794 GtkActionGroup *action_group;
795 ModestWindowPrivate *parent_priv;
796 GdkPixbuf *window_icon = NULL;
797 GError *error = NULL;
799 GtkSizeGroup *title_size_group;
800 GtkSizeGroup *value_size_group;
801 GtkWidget *window_box;
802 GtkWidget *window_align;
803 #if (GTK_MINOR_VERSION >= 10)
804 GdkAtom deserialize_type;
806 GtkWidget *from_send_hbox;
807 GtkWidget *send_icon;
808 GtkWidget *attachments_label;
810 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
811 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
813 parent_priv->ui_manager = gtk_ui_manager_new();
814 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
815 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
817 /* Add common actions */
818 gtk_action_group_add_actions (action_group,
819 modest_msg_edit_action_entries,
820 G_N_ELEMENTS (modest_msg_edit_action_entries),
822 gtk_action_group_add_actions (action_group,
823 hildon2_msg_edit_action_entries,
824 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
826 gtk_action_group_add_toggle_actions (action_group,
827 modest_msg_edit_toggle_action_entries,
828 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
830 gtk_action_group_add_radio_actions (action_group,
831 modest_msg_edit_alignment_radio_action_entries,
832 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
834 G_CALLBACK (modest_ui_actions_on_change_justify),
836 gtk_action_group_add_radio_actions (action_group,
837 modest_msg_edit_priority_action_entries,
838 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
840 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
842 gtk_action_group_add_radio_actions (action_group,
843 modest_msg_edit_file_format_action_entries,
844 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
845 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
846 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
848 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
849 g_object_unref (action_group);
851 /* Load the UI definition */
852 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
855 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
856 g_clear_error (&error);
859 /* Add accelerators */
860 gtk_window_add_accel_group (GTK_WINDOW (obj),
861 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
863 parent_priv->menubar = NULL;
865 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
866 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
868 /* Note: This ModestPairList* must exist for as long as the picker
869 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
870 * so it can't know how to manage its memory. */
871 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
872 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
874 modest_selector_picker_set_value_max_chars (MODEST_SELECTOR_PICKER (priv->from_field), MAX_FROM_VALUE);
875 modest_maemo_utils_set_hbutton_layout (title_size_group, NULL,
876 _("mail_va_from"), priv->from_field);
877 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
878 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
879 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
881 priv->to_field = modest_recpt_editor_new ();
882 priv->cc_field = modest_recpt_editor_new ();
883 priv->bcc_field = modest_recpt_editor_new ();
884 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
885 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
886 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
887 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
888 priv->priority_icon = gtk_image_new ();
889 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
890 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
891 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
892 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
893 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
894 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
895 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
896 priv->attachments_view = modest_attachments_view_new (NULL);
897 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
898 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
900 priv->header_box = gtk_vbox_new (FALSE, 0);
902 to_caption = _create_addressbook_box
903 (title_size_group, value_size_group,
904 _("mail_va_to"), priv->to_field);
905 priv->cc_caption = _create_addressbook_box
906 (title_size_group, value_size_group,
907 _("mail_va_cc"), priv->cc_field);
908 priv->bcc_caption = _create_addressbook_box
909 (title_size_group, value_size_group,
910 _("mail_va_hotfix1"), priv->bcc_field);
911 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
912 _("mail_va_subject"), FALSE, priv->subject_box);
913 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (NULL, NULL,
914 _("mail_va_attachment"),
916 priv->attachments_view,
917 HILDON_SIZE_AUTO_WIDTH |
918 HILDON_SIZE_AUTO_HEIGHT);
919 attachments_label = modest_maemo_utils_captioned_get_label_widget (priv->attachments_caption);
920 hildon_gtk_widget_set_theme_size (attachments_label, HILDON_SIZE_AUTO_HEIGHT);
923 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
924 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
925 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
926 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 148, -1);
928 g_object_unref (title_size_group);
929 g_object_unref (value_size_group);
931 from_send_hbox = gtk_hbox_new (FALSE, 0);
932 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->from_field, TRUE, TRUE, 0);
933 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
935 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
936 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
937 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
938 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
939 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
940 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
941 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
943 init_wp_text_view_style ();
945 priv->msg_body = modest_wp_text_view_new ();
948 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
949 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
950 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
951 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
952 #if (GTK_MINOR_VERSION >= 10)
953 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
954 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
956 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
957 deserialize_type, TRUE);
959 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
961 priv->find_toolbar = hildon_find_toolbar_new (NULL);
962 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
964 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
966 priv->pannable = hildon_pannable_area_new ();
968 g_object_set (G_OBJECT (priv->pannable), "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
970 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
971 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
972 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
974 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
975 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
976 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
978 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
979 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
981 window_box = gtk_vbox_new (FALSE, 0);
982 gtk_container_add (GTK_CONTAINER(obj), window_box);
984 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
986 /* Set window icon */
987 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
989 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
990 g_object_unref (window_icon);
995 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
997 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
999 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1000 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1001 priv->clipboard_change_handler_id))
1002 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1003 priv->clipboard_change_handler_id);
1004 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1005 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1006 priv->default_clipboard_change_handler_id))
1007 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1008 priv->default_clipboard_change_handler_id);
1010 if (priv->account_removed_handler_id &&
1011 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1012 priv->account_removed_handler_id))
1013 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1014 priv->account_removed_handler_id);
1018 modest_msg_edit_window_finalize (GObject *obj)
1020 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1022 /* Sanity check: shouldn't be needed, the window mgr should
1023 call this function before */
1024 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1026 if (priv->font_dialog != NULL) {
1027 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1030 if (priv->clipboard_text != NULL) {
1031 g_free (priv->clipboard_text);
1032 priv->clipboard_text = NULL;
1035 if (priv->draft_msg != NULL) {
1036 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1037 if (TNY_IS_HEADER (header)) {
1038 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1039 modest_window_mgr_unregister_header (mgr, header);
1041 g_object_unref (priv->draft_msg);
1042 priv->draft_msg = NULL;
1044 if (priv->outbox_msg != NULL) {
1045 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1046 if (TNY_IS_HEADER (header)) {
1047 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1048 modest_window_mgr_unregister_header (mgr, header);
1050 g_object_unref (priv->outbox_msg);
1051 priv->outbox_msg = NULL;
1053 if (priv->correct_scroll_idle > 0) {
1054 g_source_remove (priv->correct_scroll_idle);
1055 priv->correct_scroll_idle = 0;
1057 if (priv->scroll_drag_timeout_id > 0) {
1058 g_source_remove (priv->scroll_drag_timeout_id);
1059 priv->scroll_drag_timeout_id = 0;
1061 if (priv->clipboard_owner_idle > 0) {
1062 g_source_remove (priv->clipboard_owner_idle);
1063 priv->clipboard_owner_idle = 0;
1065 if (priv->original_account_name)
1066 g_free (priv->original_account_name);
1067 if (priv->original_mailbox)
1068 g_free (priv->original_mailbox);
1069 g_free (priv->msg_uid);
1070 g_free (priv->last_search);
1071 g_free (priv->references);
1072 g_free (priv->in_reply_to);
1073 g_object_unref (priv->faces_model);
1074 g_object_unref (priv->sizes_model);
1075 g_object_unref (priv->attachments);
1076 g_object_unref (priv->images);
1078 /* This had to stay alive for as long as the picker that used it: */
1079 modest_pair_list_free (priv->from_field_protos);
1081 G_OBJECT_CLASS(parent_class)->finalize (obj);
1085 pixbuf_size_prepared (GdkPixbufLoader *loader,
1088 ModestMsgEditWindow *self)
1090 gint new_height, new_width;
1093 new_height = height;
1097 if (width > IMAGE_MAX_WIDTH) {
1098 new_height = height * IMAGE_MAX_WIDTH / width;
1099 new_width = IMAGE_MAX_WIDTH;
1102 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1106 pixbuf_from_stream (TnyStream *stream,
1107 const gchar *mime_type,
1108 guint64 *stream_size,
1109 ModestMsgEditWindow *self)
1111 GdkPixbufLoader *loader;
1114 GError *error = NULL;
1118 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1120 if (loader == NULL) {
1125 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1127 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1129 tny_stream_reset (TNY_STREAM (stream));
1130 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1131 unsigned char read_buffer[128];
1133 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1135 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1138 /* Allow some UI responsiveness */
1139 while (gtk_events_pending ())
1140 gtk_main_iteration ();
1142 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1144 gdk_pixbuf_loader_close (loader, &error);
1147 g_error_free (error);
1148 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1150 g_object_ref (pixbuf);
1151 g_object_unref (loader);
1156 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1157 GdkPixbuf *new_pixbuf;
1159 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1160 gdk_pixbuf_get_width (pixbuf);
1161 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1162 g_object_unref (pixbuf);
1163 pixbuf = new_pixbuf;
1167 *stream_size = size;
1173 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1175 ModestMsgEditWindowPrivate *priv;
1178 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1180 g_object_ref (self);
1181 for (iter = tny_list_create_iterator (attachments);
1182 !tny_iterator_is_done (iter);
1183 tny_iterator_next (iter)) {
1184 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1185 const gchar *cid = tny_mime_part_get_content_id (part);
1186 const gchar *mime_type = tny_mime_part_get_content_type (part);
1187 if ((cid != NULL)&&(mime_type != NULL)) {
1188 guint64 stream_size;
1189 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1190 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1193 g_object_unref (stream);
1195 if (pixbuf != NULL) {
1196 priv->images_count ++;
1197 priv->images_size += stream_size;
1198 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1199 g_object_unref (pixbuf);
1202 g_object_unref (part);
1204 g_object_unref (iter);
1205 g_object_unref (self);
1209 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1211 TnyMimePart *parent = NULL;
1212 const gchar *content_type = NULL;
1213 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1215 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1217 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1218 parent = g_object_ref (msg);
1219 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1220 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1223 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1224 iter = tny_list_create_iterator (parts);
1225 while (!tny_iterator_is_done (iter)) {
1227 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1228 content_type = tny_mime_part_get_content_type (part);
1229 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1233 g_object_unref (part);
1235 tny_iterator_next (iter);
1237 g_object_unref (iter);
1238 g_object_unref (parts);
1241 if (parent != NULL) {
1242 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1245 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1246 iter = tny_list_create_iterator (parts);
1247 while (!tny_iterator_is_done (iter)) {
1249 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1250 content_type = tny_mime_part_get_content_type (part);
1251 if (content_type && g_str_has_prefix (content_type, "image/")) {
1252 tny_list_prepend (priv->images, (GObject *) part);
1254 g_object_unref (part);
1255 tny_iterator_next (iter);
1257 g_object_unref (iter);
1258 g_object_unref (parts);
1259 g_object_unref (parent);
1264 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1267 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1269 for (iter = tny_list_create_iterator (attachments) ;
1270 !tny_iterator_is_done (iter);
1271 tny_iterator_next (iter)) {
1272 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1273 const gchar *cid = tny_mime_part_get_content_id (part);
1275 char *invalid = NULL;
1276 gint int_cid = strtol (cid, &invalid, 10);
1277 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1278 priv->next_cid = int_cid + 1;
1281 g_object_unref (part);
1283 g_object_unref (iter);
1287 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1290 gchar *to, *cc, *bcc, *subject;
1292 ModestMsgEditWindowPrivate *priv;
1293 ModestWindowPrivate *parent_priv;
1295 TnyHeaderFlags priority_flags;
1296 TnyFolder *msg_folder;
1297 gboolean is_html = FALSE;
1298 gboolean field_view_set;
1300 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1301 g_return_if_fail (TNY_IS_MSG (msg));
1303 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1304 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1306 header = tny_msg_get_header (msg);
1307 to = tny_header_dup_to (header);
1308 cc = tny_header_dup_cc (header);
1309 bcc = tny_header_dup_bcc (header);
1310 subject = tny_header_dup_subject (header);
1312 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1313 priority_flags = tny_header_get_priority (header);
1316 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1318 field_view_set = TRUE;
1320 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1321 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1322 gtk_widget_show (priv->cc_caption);
1323 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1324 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1325 gtk_widget_hide (priv->cc_caption);
1326 field_view_set = FALSE;
1328 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1330 field_view_set = TRUE;
1332 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1333 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1334 gtk_widget_show (priv->bcc_caption);
1335 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1336 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1337 gtk_widget_hide (priv->bcc_caption);
1338 field_view_set = FALSE;
1340 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1344 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1345 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1348 update_window_title (self);
1350 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1351 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1353 if ((body == NULL)||(body[0] == '\0')) {
1355 body = modest_text_utils_convert_to_html ("");
1358 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1359 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1362 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1365 /* Add attachments to the view */
1366 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1367 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1368 if (tny_list_get_length (priv->attachments) == 0) {
1369 gtk_widget_hide (priv->attachments_caption);
1371 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1372 gtk_widget_show_all (priv->attachments_caption);
1374 get_related_images (self, msg);
1375 update_next_cid (self, priv->attachments);
1376 update_next_cid (self, priv->images);
1377 replace_with_images (self, priv->images);
1379 if (preserve_is_rich && !is_html) {
1380 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1381 /* Get the default format required from configuration */
1382 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1383 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1386 /* Set the default focus depending on having already a To: field or not */
1387 if ((!to)||(*to == '\0')) {
1388 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1390 gtk_widget_grab_focus (priv->msg_body);
1393 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1395 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1396 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1398 modest_msg_edit_window_set_modified (self, FALSE);
1400 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1401 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1402 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1403 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1405 if (priv->msg_uid) {
1406 g_free (priv->msg_uid);
1407 priv->msg_uid = NULL;
1410 /* we should set a reference to the incoming message if it is a draft */
1411 msg_folder = tny_msg_get_folder (msg);
1413 if (modest_tny_folder_is_local_folder (msg_folder)) {
1414 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1415 if (type == TNY_FOLDER_TYPE_INVALID)
1416 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1418 if (type == TNY_FOLDER_TYPE_DRAFTS)
1419 priv->draft_msg = g_object_ref(msg);
1420 if (type == TNY_FOLDER_TYPE_OUTBOX)
1421 priv->outbox_msg = g_object_ref(msg);
1422 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1424 g_object_unref (msg_folder);
1435 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1437 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1438 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1439 GtkWidget *placeholder;
1440 GtkWidget *tool_item;
1445 GtkWidget *sizes_menu;
1446 GtkWidget *fonts_menu;
1452 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1453 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1454 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1455 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1457 /* Font color placeholder */
1458 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1459 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1462 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1463 priv->font_color_button = hildon_color_button_new ();
1464 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1465 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1466 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1467 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1468 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1469 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1470 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1471 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1473 G_CALLBACK (modest_msg_edit_window_color_button_change),
1476 /* Font size and face placeholder */
1477 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1478 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1480 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1481 priv->size_tool_button_label = gtk_label_new (NULL);
1482 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1483 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1484 size_text, "</span>", NULL);
1485 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1486 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1488 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1489 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1490 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1491 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1492 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1493 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1494 gtk_widget_set_sensitive (arrow, FALSE);
1495 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1496 sizes_menu = gtk_menu_new ();
1497 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1498 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1501 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1502 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1504 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1508 if (wp_font_size[size_index] == 12)
1509 priv->current_size_index = size_index;
1513 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1514 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1515 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1516 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1517 priv->font_size_toolitem = tool_item;
1520 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1521 priv->font_tool_button_label = gtk_label_new (NULL);
1522 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1523 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1524 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1526 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1527 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1528 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1529 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1530 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1531 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1532 gtk_widget_set_sensitive (arrow, FALSE);
1533 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1534 fonts_menu = gtk_menu_new ();
1535 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1536 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1539 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1541 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1542 0, wp_get_font_name (font_index),
1545 if (font_index == DEFAULT_FONT)
1546 priv->current_face_index = font_index;
1548 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1549 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1550 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1551 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1552 priv->font_face_toolitem = tool_item;
1554 /* Set expand and homogeneous for remaining items */
1555 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1556 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1557 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1558 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1559 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1560 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1562 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1563 will not show the tool items added to the placeholders) */
1564 gtk_widget_show_all (parent_priv->toolbar);
1566 /* Set the no show all *after* showing all items. We do not
1567 want the toolbar to be shown with a show all because it
1568 could go agains the gconf setting regarding showing or not
1569 the toolbar of the editor window */
1570 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1576 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1579 ModestWindowPrivate *parent_priv;
1580 ModestMsgEditWindowPrivate *priv;
1581 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1582 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1583 ModestWindowMgr *mgr = NULL;
1585 g_return_val_if_fail (msg, NULL);
1586 g_return_val_if_fail (account_name, NULL);
1588 mgr = modest_runtime_get_window_mgr ();
1590 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1592 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1593 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1595 /* Menubar. Update the state of some toggles */
1596 priv->from_field_protos = get_transports ();
1597 priv->original_mailbox = NULL;
1598 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1599 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 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1602 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1603 priv->original_mailbox = g_strdup (mailbox);
1604 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1605 /* We set the first mailbox as the active mailbox */
1606 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1607 if (priv->original_mailbox != NULL)
1608 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1609 (gpointer) priv->original_mailbox);
1611 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1612 (gpointer) account_name);
1614 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1616 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1617 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1619 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1620 hildon_touch_selector_get_current_text
1621 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1622 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1623 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1626 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1628 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1630 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1631 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1633 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1635 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1636 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1637 /* Add common dimming rules */
1638 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1639 modest_msg_edit_window_toolbar_dimming_entries,
1640 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1641 MODEST_WINDOW (obj));
1642 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1643 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1644 MODEST_WINDOW (obj));
1645 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1646 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1647 MODEST_WINDOW (obj));
1648 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1649 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1650 MODEST_WINDOW (obj));
1651 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1652 G_CALLBACK (modest_ui_dimming_rules_on_send),
1653 MODEST_WINDOW (obj));
1654 /* Insert dimming rules group for this window */
1655 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1656 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1658 /* Setup app menu */
1659 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1661 /* Checks the dimming rules */
1662 g_object_unref (toolbar_rules_group);
1663 g_object_unref (clipboard_rules_group);
1664 gtk_widget_hide (priv->priority_icon);
1665 gtk_widget_queue_resize (priv->subject_box);
1666 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1668 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1670 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1671 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1672 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1673 priv->update_caption_visibility = TRUE;
1675 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1677 /* Track account-removed signal, this window should be closed
1678 in the case we're creating a mail associated to the account
1680 priv->account_removed_handler_id =
1681 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1683 G_CALLBACK(on_account_removed),
1686 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1688 return (ModestWindow*) obj;
1692 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1694 GString **string_buffer = (GString **) user_data;
1696 *string_buffer = g_string_append (*string_buffer, buffer);
1702 * @result: A new string which should be freed with g_free().
1705 get_formatted_data (ModestMsgEditWindow *edit_window)
1707 ModestMsgEditWindowPrivate *priv;
1708 GString *string_buffer = g_string_new ("");
1710 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1712 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1714 modest_text_utils_hyperlinkify (string_buffer);
1716 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1718 return g_string_free (string_buffer, FALSE);
1723 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1726 const gchar *account_name;
1727 ModestMsgEditWindowPrivate *priv;
1728 TnyIterator *att_iter;
1729 const gchar *picker_active_id;
1731 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1733 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1735 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1736 g_return_val_if_fail (picker_active_id, NULL);
1737 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1739 /* don't free these (except from) */
1740 data = g_slice_new0 (MsgData);
1741 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1742 data->account_name = g_strdup (account_name);
1743 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1744 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1745 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1746 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1747 data->references = g_strdup (priv->references);
1748 data->in_reply_to = g_strdup (priv->in_reply_to);
1749 if (priv->draft_msg) {
1750 data->draft_msg = g_object_ref (priv->draft_msg);
1751 } else if (priv->outbox_msg) {
1752 data->draft_msg = g_object_ref (priv->outbox_msg);
1754 data->draft_msg = NULL;
1757 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1759 gtk_text_buffer_get_bounds (buf, &b, &e);
1760 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1762 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1763 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1765 data->html_body = NULL;
1767 /* deep-copy the data */
1768 att_iter = tny_list_create_iterator (priv->attachments);
1769 data->attachments = NULL;
1770 while (!tny_iterator_is_done (att_iter)) {
1771 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1772 if (!(TNY_IS_MIME_PART(part))) {
1773 g_warning ("strange data in attachment list");
1774 g_object_unref (part);
1775 tny_iterator_next (att_iter);
1778 data->attachments = g_list_append (data->attachments,
1780 tny_iterator_next (att_iter);
1782 g_object_unref (att_iter);
1784 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1785 att_iter = tny_list_create_iterator (priv->images);
1786 data->images = NULL;
1787 while (!tny_iterator_is_done (att_iter)) {
1788 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1790 if (!(TNY_IS_MIME_PART(part))) {
1791 g_warning ("strange data in attachment list");
1792 g_object_unref (part);
1793 tny_iterator_next (att_iter);
1796 cid = tny_mime_part_get_content_id (part);
1798 gchar *image_tag_id;
1799 GtkTextTag *image_tag;
1801 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1802 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1803 g_free (image_tag_id);
1805 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1807 ((gtk_text_iter_has_tag (&iter, image_tag))||
1808 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1809 data->images = g_list_append (data->images,
1810 g_object_ref (part));
1812 g_object_unref (part);
1813 tny_iterator_next (att_iter);
1815 g_object_unref (att_iter);
1817 data->priority_flags = priv->priority_flags;
1824 unref_gobject (GObject *obj, gpointer data)
1826 if (!G_IS_OBJECT(obj))
1828 g_object_unref (obj);
1832 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1835 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1843 g_free (data->from);
1844 g_free (data->subject);
1845 g_free (data->plain_body);
1846 g_free (data->html_body);
1847 g_free (data->account_name);
1848 g_free (data->references);
1849 g_free (data->in_reply_to);
1851 if (data->draft_msg != NULL) {
1852 g_object_unref (data->draft_msg);
1853 data->draft_msg = NULL;
1856 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1857 g_list_free (data->attachments);
1858 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1859 g_list_free (data->images);
1861 g_slice_free (MsgData, data);
1865 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1867 guint64 *parts_size)
1869 ModestMsgEditWindowPrivate *priv;
1871 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1873 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1875 /* TODO: add images */
1876 *parts_size += priv->images_size;
1877 *parts_count += priv->images_count;
1882 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1885 ModestMsgEditWindowPrivate *priv = NULL;
1886 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1888 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1890 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1892 return MODEST_MSG_EDIT_FORMAT_HTML;
1894 return MODEST_MSG_EDIT_FORMAT_TEXT;
1898 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1899 ModestMsgEditFormat format)
1901 ModestMsgEditWindowPrivate *priv;
1902 ModestWindowPrivate *parent_priv;
1904 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1905 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1906 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1909 case MODEST_MSG_EDIT_FORMAT_HTML:
1910 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1911 if (parent_priv->toolbar) gtk_widget_show (parent_priv->toolbar);
1913 case MODEST_MSG_EDIT_FORMAT_TEXT:
1914 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1915 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
1918 g_return_if_reached ();
1922 ModestMsgEditFormatState *
1923 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1925 ModestMsgEditFormatState *format_state = NULL;
1926 ModestMsgEditWindowPrivate *priv;
1927 WPTextBufferFormat *buffer_format;
1929 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1931 buffer_format = g_new0 (WPTextBufferFormat, 1);
1932 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1934 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1936 format_state = g_new0 (ModestMsgEditFormatState, 1);
1937 format_state->bold = buffer_format->bold&0x1;
1938 format_state->italics = buffer_format->italic&0x1;
1939 format_state->bullet = buffer_format->bullet&0x1;
1940 format_state->color = buffer_format->color;
1941 format_state->font_size = buffer_format->font_size;
1942 format_state->font_family = wp_get_font_name (buffer_format->font);
1943 format_state->justification = buffer_format->justification;
1944 g_free (buffer_format);
1946 return format_state;
1951 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1952 const ModestMsgEditFormatState *format_state)
1954 ModestMsgEditWindowPrivate *priv;
1955 WPTextBufferFormat *buffer_format;
1956 WPTextBufferFormat *current_format;
1958 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1959 g_return_if_fail (format_state != NULL);
1961 buffer_format = g_new0 (WPTextBufferFormat, 1);
1962 current_format = g_new0 (WPTextBufferFormat, 1);
1964 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1965 gtk_widget_grab_focus (priv->msg_body);
1966 buffer_format->bold = (format_state->bold != FALSE);
1967 buffer_format->italic = (format_state->italics != FALSE);
1968 buffer_format->color = format_state->color;
1969 buffer_format->font_size = format_state->font_size;
1970 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1971 buffer_format->justification = format_state->justification;
1972 buffer_format->bullet = format_state->bullet;
1974 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1976 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1977 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1978 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1979 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1980 buffer_format->cs.font = (buffer_format->font != current_format->font);
1981 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1982 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1984 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1985 if (buffer_format->cs.bold) {
1986 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1987 GINT_TO_POINTER (buffer_format->bold&0x1));
1989 if (buffer_format->cs.italic) {
1990 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1991 GINT_TO_POINTER (buffer_format->italic&0x1));
1993 if (buffer_format->cs.color) {
1994 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1995 GINT_TO_POINTER (&(buffer_format->color)));
1997 if (buffer_format->cs.font_size) {
1998 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1999 GINT_TO_POINTER (buffer_format->font_size));
2001 if (buffer_format->cs.justification) {
2002 switch (buffer_format->justification) {
2003 case GTK_JUSTIFY_LEFT:
2004 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2005 GINT_TO_POINTER(TRUE));
2007 case GTK_JUSTIFY_CENTER:
2008 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2009 GINT_TO_POINTER(TRUE));
2011 case GTK_JUSTIFY_RIGHT:
2012 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2013 GINT_TO_POINTER(TRUE));
2020 if (buffer_format->cs.font) {
2021 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2022 GINT_TO_POINTER (buffer_format->font));
2024 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2025 if (buffer_format->cs.bullet) {
2026 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2027 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2029 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2031 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2033 g_free (buffer_format);
2034 g_free (current_format);
2036 /* Check dimming rules */
2037 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2038 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2042 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2044 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2046 ModestWindowPrivate *parent_priv;
2047 ModestMsgEditWindowPrivate *priv;
2049 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2050 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2052 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2053 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2054 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2055 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2057 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2058 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2059 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2062 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2064 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2065 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2067 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2068 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2070 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2071 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2074 switch (buffer_format->justification)
2076 case GTK_JUSTIFY_LEFT:
2077 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2079 case GTK_JUSTIFY_CENTER:
2080 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2082 case GTK_JUSTIFY_RIGHT:
2083 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2090 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2092 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2093 G_CALLBACK (modest_msg_edit_window_color_button_change),
2095 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2096 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2097 G_CALLBACK (modest_msg_edit_window_color_button_change),
2100 if (priv->current_size_index != buffer_format->font_size) {
2104 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2105 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2109 priv->current_size_index = buffer_format->font_size;
2111 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2112 markup = g_strconcat ("<span font_family='Sans'>",
2113 size_text, "</span>", NULL);
2115 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2119 gtk_tree_path_free (path);
2122 if (priv->current_face_index != buffer_format->font) {
2126 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2127 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2131 priv->current_face_index = buffer_format->font;
2132 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2133 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2134 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2141 g_free (buffer_format);
2145 #ifdef MODEST_HILDON_VERSION_0
2147 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2150 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2151 ModestMsgEditWindowPrivate *priv;
2152 GtkWidget *dialog = NULL;
2154 GdkColor *new_color = NULL;
2156 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2157 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2159 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2160 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2161 g_free (buffer_format);
2163 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2164 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2165 if (new_color != NULL) {
2166 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2167 (gpointer) new_color);
2170 gtk_widget_destroy (dialog);
2175 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2178 ModestMsgEditWindowPrivate *priv;
2179 GtkWidget *dialog = NULL;
2181 GdkColor *old_color = NULL;
2182 const GdkColor *new_color = NULL;
2184 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2185 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2187 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2188 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2190 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2191 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2192 if (new_color != NULL)
2193 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2195 gtk_widget_destroy (dialog);
2201 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2204 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2205 ModestMsgEditWindowPrivate *priv;
2206 GtkWidget *dialog = NULL;
2208 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2209 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2211 dialog = hildon_color_chooser_new ();
2212 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2213 g_free (buffer_format);
2215 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2217 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2218 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2221 gtk_widget_destroy (dialog);
2226 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2229 ModestMsgEditWindowPrivate *priv;
2230 GtkWidget *dialog = NULL;
2231 GdkColor *old_color = NULL;
2233 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2234 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2236 dialog = hildon_color_chooser_new ();
2237 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2239 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2241 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2242 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2244 gtk_widget_destroy (dialog);
2247 #endif /*!MODEST_HILDON_VERSION_0*/
2252 create_stream_for_uri (const gchar* uri)
2257 TnyStream *result = NULL;
2259 GnomeVFSHandle *handle = NULL;
2260 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2261 if (test == GNOME_VFS_OK) {
2262 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2263 /* Streams over OBEX (Bluetooth) are not seekable but
2264 * we expect them to be (we might need to read them
2265 * several times). So if this is a Bluetooth URI just
2266 * read the whole file into memory (this is not a fast
2267 * protocol so we can assume that these files are not
2268 * going to be very big) */
2269 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2270 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2271 TnyStream *memstream = tny_camel_mem_stream_new ();
2272 tny_stream_write_to_stream (vfssstream, memstream);
2273 g_object_unref (vfssstream);
2276 result = vfssstream;
2284 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2287 ModestMsgEditWindowPrivate *priv;
2288 GtkWidget *dialog = NULL;
2290 GSList *uris = NULL;
2291 GSList *uri_node = NULL;
2293 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2295 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2296 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2297 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2299 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2301 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2302 GTK_WINDOW (dialog), GTK_WINDOW (window));
2304 response = gtk_dialog_run (GTK_DIALOG (dialog));
2306 case GTK_RESPONSE_OK:
2308 gchar *current_folder;
2309 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2310 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2311 if (current_folder && current_folder != '\0') {
2313 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2314 current_folder, &err);
2316 g_debug ("Error storing latest used folder: %s", err->message);
2320 g_free (current_folder);
2326 gtk_widget_destroy (dialog);
2328 g_object_ref (window);
2329 /* The operation could take some time so allow the dialog to be closed */
2330 while (gtk_events_pending ())
2331 gtk_main_iteration ();
2333 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2335 GnomeVFSHandle *handle = NULL;
2336 GnomeVFSResult result;
2337 GtkTextIter position;
2338 GtkTextMark *insert_mark;
2340 uri = (const gchar *) uri_node->data;
2341 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2342 if (result == GNOME_VFS_OK) {
2344 GnomeVFSFileInfo *info;
2345 gchar *filename, *basename, *escaped_filename;
2346 TnyMimePart *mime_part;
2348 const gchar *mime_type = NULL;
2349 GnomeVFSURI *vfs_uri;
2350 guint64 stream_size;
2352 gnome_vfs_close (handle);
2353 vfs_uri = gnome_vfs_uri_new (uri);
2355 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2356 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2357 g_free (escaped_filename);
2358 gnome_vfs_uri_unref (vfs_uri);
2359 info = gnome_vfs_file_info_new ();
2361 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2362 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2364 mime_type = gnome_vfs_file_info_get_mime_type (info);
2366 mime_part = tny_platform_factory_new_mime_part
2367 (modest_runtime_get_platform_factory ());
2369 TnyStream *stream = create_stream_for_uri (uri);
2371 if (stream == NULL) {
2373 modest_platform_information_banner (NULL, NULL,
2374 _FM("sfil_ib_opening_not_allowed"));
2376 g_object_unref (mime_part);
2377 gnome_vfs_file_info_unref (info);
2381 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2383 content_id = g_strdup_printf ("%d", priv->next_cid);
2384 tny_mime_part_set_content_id (mime_part, content_id);
2385 g_free (content_id);
2388 basename = g_path_get_basename (filename);
2389 tny_mime_part_set_filename (mime_part, basename);
2392 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2394 if (pixbuf != NULL) {
2395 priv->images_size += stream_size;
2396 priv->images_count ++;
2397 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2398 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2399 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2400 tny_mime_part_get_content_id (mime_part), pixbuf);
2401 g_object_unref (pixbuf);
2403 tny_list_prepend (priv->images, (GObject *) mime_part);
2404 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2406 modest_platform_information_banner (NULL, NULL,
2407 _("mail_ib_file_operation_failed"));
2411 g_object_unref (mime_part);
2412 gnome_vfs_file_info_unref (info);
2416 g_object_unref (window);
2420 on_attach_file_response (GtkDialog *dialog,
2424 GSList *uris = NULL;
2426 GnomeVFSFileSize total_size, allowed_size;
2427 ModestMsgEditWindow *window;
2428 ModestMsgEditWindowPrivate *priv;
2433 case GTK_RESPONSE_OK:
2435 gchar *current_folder;
2437 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2438 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2439 if (current_folder && current_folder != '\0') {
2441 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2442 current_folder, &err);
2444 g_debug ("Error storing latest used folder: %s", err->message);
2448 g_free (current_folder);
2455 window = MODEST_MSG_EDIT_WINDOW (user_data);
2456 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2458 /* allowed size is the maximum size - what's already there */
2459 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2460 &att_num, &att_size);
2461 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2464 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2466 const gchar *uri = (const gchar *) uri_node->data;
2469 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2471 if (total_size > allowed_size) {
2472 g_warning ("%s: total size: %u",
2473 __FUNCTION__, (unsigned int)total_size);
2476 allowed_size -= total_size;
2478 g_slist_foreach (uris, (GFunc) g_free, NULL);
2479 g_slist_free (uris);
2481 gtk_widget_destroy (GTK_WIDGET (dialog));
2485 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2487 GtkWidget *dialog = NULL;
2488 ModestMsgEditWindowPrivate *priv;
2491 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2493 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2495 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2498 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2499 GTK_FILE_CHOOSER_ACTION_OPEN);
2500 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2501 conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2502 if (conf_folder && conf_folder[0] != '\0') {
2503 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2506 /* Set the default folder to images folder */
2507 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2508 ".documents", NULL);
2509 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2510 g_free (docs_folder);
2512 g_free (conf_folder);
2513 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2514 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2515 GTK_WINDOW (dialog), GTK_WINDOW (window));
2517 /* Connect to response & show */
2518 g_signal_connect (dialog, "response",
2519 G_CALLBACK (on_attach_file_response), window);
2520 gtk_widget_show (dialog);
2525 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2527 GnomeVFSFileSize allowed_size)
2530 GnomeVFSHandle *handle = NULL;
2531 ModestMsgEditWindowPrivate *priv;
2532 GnomeVFSResult result;
2533 GnomeVFSFileSize size = 0;
2534 g_return_val_if_fail (window, 0);
2535 g_return_val_if_fail (uri, 0);
2537 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2539 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2540 if (result == GNOME_VFS_OK) {
2541 TnyMimePart *mime_part;
2543 const gchar *mime_type = NULL;
2545 gchar *escaped_filename;
2548 GnomeVFSFileInfo *info;
2549 GnomeVFSURI *vfs_uri;
2551 gnome_vfs_close (handle);
2552 vfs_uri = gnome_vfs_uri_new (uri);
2555 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2556 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2557 g_free (escaped_filename);
2558 gnome_vfs_uri_unref (vfs_uri);
2560 info = gnome_vfs_file_info_new ();
2562 if (gnome_vfs_get_file_info (uri,
2564 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2566 mime_type = gnome_vfs_file_info_get_mime_type (info);
2567 mime_part = tny_platform_factory_new_mime_part
2568 (modest_runtime_get_platform_factory ());
2570 /* try to get the attachment's size; this may fail for weird
2571 * file systems, like obex, upnp... */
2572 if (allowed_size != 0 &&
2573 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2575 if (size > allowed_size) {
2576 modest_platform_information_banner (NULL, NULL,
2577 _FM("sfil_ib_opening_not_allowed"));
2582 g_warning ("%s: could not get attachment size", __FUNCTION__);
2584 stream = create_stream_for_uri (uri);
2586 if (stream == NULL) {
2588 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2590 g_object_unref (mime_part);
2592 gnome_vfs_file_info_unref (info);
2596 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2597 g_object_unref (stream);
2599 content_id = g_strdup_printf ("%d", priv->next_cid);
2600 tny_mime_part_set_content_id (mime_part, content_id);
2601 g_free (content_id);
2604 basename = g_path_get_basename (filename);
2605 tny_mime_part_set_filename (mime_part, basename);
2608 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2609 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2611 info->size == 0, info->size);
2612 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2613 gtk_widget_show_all (priv->attachments_caption);
2614 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2616 g_object_unref (mime_part);
2617 gnome_vfs_file_info_unref (info);
2624 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2627 ModestMsgEditWindowPrivate *priv;
2630 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2631 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2633 if (att_list == NULL) {
2634 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2635 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2636 g_object_unref (att_list);
2640 g_object_ref (att_list);
2643 if (tny_list_get_length (att_list) == 0) {
2644 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2646 gboolean dialog_response;
2647 gchar *message = NULL;
2648 gchar *filename = NULL;
2650 if (tny_list_get_length (att_list) == 1) {
2652 iter = tny_list_create_iterator (att_list);
2653 part = (TnyMimePart *) tny_iterator_get_current (iter);
2654 g_object_unref (iter);
2655 if (TNY_IS_MSG (part)) {
2656 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2658 filename = tny_header_dup_subject (header);
2659 g_object_unref (header);
2661 if (filename == NULL) {
2662 filename = g_strdup (_("mail_va_no_subject"));
2665 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2667 g_object_unref (part);
2669 filename = g_strdup ("");
2671 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2672 "emev_nc_delete_attachments",
2673 tny_list_get_length (att_list)), filename);
2676 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2680 if (dialog_response != GTK_RESPONSE_OK) {
2681 g_object_unref (att_list);
2685 for (iter = tny_list_create_iterator (att_list);
2686 !tny_iterator_is_done (iter);
2687 tny_iterator_next (iter)) {
2688 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2689 const gchar *att_id;
2690 tny_list_remove (priv->attachments, (GObject *) mime_part);
2692 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2694 if (tny_list_get_length (priv->attachments) == 0)
2695 gtk_widget_hide (priv->attachments_caption);
2696 att_id = tny_mime_part_get_content_id (mime_part);
2698 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2700 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2701 g_object_unref (mime_part);
2703 g_object_unref (iter);
2706 g_object_unref (att_list);
2708 /* if the last attachment has been removed, focus the Subject: field */
2709 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2710 gtk_widget_grab_focus (priv->subject_field);
2714 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2717 ModestMsgEditWindowPrivate *priv;
2718 GdkColor *new_color;
2719 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2721 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2722 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2725 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2727 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2729 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2731 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2736 font_size_clicked (GtkToolButton *button,
2737 ModestMsgEditWindow *window)
2739 ModestMsgEditWindowPrivate *priv;
2740 GtkWidget *selector, *dialog;
2742 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2744 selector = hildon_touch_selector_new ();
2745 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2746 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2748 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2749 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2750 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2752 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2756 WPTextBufferFormat format;
2758 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2760 memset (&format, 0, sizeof (format));
2761 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2763 format.cs.font_size = TRUE;
2764 format.cs.text_position = TRUE;
2765 format.cs.font = TRUE;
2766 format.font_size = new_index;
2767 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2769 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2770 GINT_TO_POINTER (new_index)))
2771 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2773 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2774 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2775 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2776 size_text, "</span>", NULL);
2778 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2782 gtk_widget_destroy (dialog);
2784 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2789 font_face_clicked (GtkToolButton *button,
2790 ModestMsgEditWindow *window)
2792 ModestMsgEditWindowPrivate *priv;
2793 GtkWidget *selector, *dialog;
2794 GtkCellRenderer *renderer;
2796 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2798 selector = hildon_touch_selector_new ();
2799 renderer = gtk_cell_renderer_text_new ();
2800 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2801 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2802 renderer, "family", 0, "text", 0, NULL);
2803 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2805 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2806 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2807 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2809 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2810 gint new_font_index;
2814 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2815 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2816 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2820 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2822 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2823 GINT_TO_POINTER(new_font_index)))
2824 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2826 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2827 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2829 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2833 gtk_tree_path_free (path);
2836 gtk_widget_destroy (dialog);
2838 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2843 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2846 ModestMsgEditWindowPrivate *priv = NULL;
2847 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2849 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2850 if (!priv->update_caption_visibility)
2853 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2855 gtk_widget_show (priv->cc_caption);
2857 gtk_widget_hide (priv->cc_caption);
2859 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2863 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2866 ModestMsgEditWindowPrivate *priv = NULL;
2867 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2869 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2870 if (!priv->update_caption_visibility)
2873 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2875 gtk_widget_show (priv->bcc_caption);
2877 gtk_widget_hide (priv->bcc_caption);
2879 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2883 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2884 ModestRecptEditor *editor)
2886 ModestMsgEditWindowPrivate *priv;
2888 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2889 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2891 /* we check for low-mem; in that case, show a warning, and don't allow
2892 * for the addressbook
2894 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2897 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2899 if (editor == NULL) {
2900 GtkWidget *view_focus;
2901 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2903 /* This code should be kept in sync with ModestRecptEditor. The
2904 textview inside the recpt editor is the one that really gets the
2905 focus. As it's inside a scrolled window, and this one inside the
2906 hbox recpt editor inherits from, we'll need to go up in the
2907 hierarchy to know if the text view is part of the recpt editor
2908 or if it's a different text entry */
2910 if (gtk_widget_get_parent (view_focus)) {
2911 GtkWidget *first_parent;
2913 first_parent = gtk_widget_get_parent (view_focus);
2914 if (gtk_widget_get_parent (first_parent) &&
2915 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2916 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2921 editor = MODEST_RECPT_EDITOR (priv->to_field);
2925 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
2929 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2931 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2933 modest_msg_edit_window_open_addressbook (window, NULL);
2937 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2938 gboolean show_toolbar)
2940 ModestWindowPrivate *parent_priv;
2941 ModestMsgEditWindowPrivate *priv;
2943 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2944 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2945 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2947 /* We can not just use the code of
2948 modest_msg_edit_window_setup_toolbar because it has a
2949 mixture of both initialization and creation code. */
2951 gint current_format;
2952 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2953 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2954 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
2955 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2957 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2960 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2965 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2966 TnyHeaderFlags priority_flags)
2968 ModestMsgEditWindowPrivate *priv;
2969 ModestWindowPrivate *parent_priv;
2971 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2973 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2974 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2976 if (priv->priority_flags != priority_flags) {
2977 GtkAction *priority_action = NULL;
2979 priv->priority_flags = priority_flags;
2981 switch (priority_flags) {
2982 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2983 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2984 MODEST_HEADER_ICON_HIGH,
2985 HILDON_ICON_SIZE_SMALL);
2986 gtk_widget_show (priv->priority_icon);
2987 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2988 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2990 case TNY_HEADER_FLAG_LOW_PRIORITY:
2991 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2992 MODEST_HEADER_ICON_LOW,
2993 HILDON_ICON_SIZE_SMALL);
2994 gtk_widget_show (priv->priority_icon);
2995 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2996 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2999 gtk_widget_hide (priv->priority_icon);
3000 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3001 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3004 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3005 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3007 gtk_widget_queue_resize (priv->subject_box);
3011 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3014 ModestMsgEditWindowPrivate *priv;
3015 ModestWindowPrivate *parent_priv;
3016 gint current_format;
3018 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3020 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3021 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3023 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3024 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3026 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3028 if (parent_priv->toolbar) {
3029 if (file_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3030 gtk_widget_hide (parent_priv->toolbar);
3032 gtk_widget_show (parent_priv->toolbar);
3036 if (current_format != file_format) {
3037 switch (file_format) {
3038 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3039 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3040 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3042 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3046 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3047 response = gtk_dialog_run (GTK_DIALOG (dialog));
3048 gtk_widget_destroy (dialog);
3049 if (response == GTK_RESPONSE_OK) {
3050 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3051 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
3053 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3054 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3059 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3060 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3061 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3066 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3069 ModestMsgEditWindowPrivate *priv;
3070 WPTextBufferFormat oldfmt, fmt;
3071 gint old_position = 0;
3075 GdkColor *color = NULL;
3076 gboolean bold, bold_set, italic, italic_set;
3077 gboolean underline, underline_set;
3078 gboolean strikethrough, strikethrough_set;
3079 gboolean position_set;
3080 gboolean font_size_set, font_set, color_set;
3083 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3084 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3086 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3087 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3088 GTK_WINDOW(dialog), GTK_WINDOW (window));
3090 /* First we get the currently selected font information */
3091 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3093 switch (oldfmt.text_position) {
3094 case TEXT_POSITION_NORMAL:
3097 case TEXT_POSITION_SUPERSCRIPT:
3105 g_object_set (G_OBJECT (dialog),
3106 "bold", oldfmt.bold != FALSE,
3107 "bold-set", !oldfmt.cs.bold,
3108 "underline", oldfmt.underline != FALSE,
3109 "underline-set", !oldfmt.cs.underline,
3110 "italic", oldfmt.italic != FALSE,
3111 "italic-set", !oldfmt.cs.italic,
3112 "strikethrough", oldfmt.strikethrough != FALSE,
3113 "strikethrough-set", !oldfmt.cs.strikethrough,
3114 "color", &oldfmt.color,
3115 "color-set", !oldfmt.cs.color,
3116 "size", wp_font_size[oldfmt.font_size],
3117 "size-set", !oldfmt.cs.font_size,
3118 "position", old_position,
3119 "position-set", !oldfmt.cs.text_position,
3120 "family", wp_get_font_name (oldfmt.font),
3121 "family-set", !oldfmt.cs.font,
3124 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3125 GTK_WINDOW (dialog), GTK_WINDOW (window));
3126 gtk_widget_show_all (dialog);
3127 priv->font_dialog = dialog;
3128 response = gtk_dialog_run (GTK_DIALOG (dialog));
3129 priv->font_dialog = NULL;
3130 if (response == GTK_RESPONSE_OK) {
3132 g_object_get( dialog,
3134 "bold-set", &bold_set,
3135 "underline", &underline,
3136 "underline-set", &underline_set,
3138 "italic-set", &italic_set,
3139 "strikethrough", &strikethrough,
3140 "strikethrough-set", &strikethrough_set,
3142 "color-set", &color_set,
3144 "size-set", &font_size_set,
3145 "family", &font_name,
3146 "family-set", &font_set,
3147 "position", &position,
3148 "position-set", &position_set,
3153 if (response == GTK_RESPONSE_OK) {
3154 memset(&fmt, 0, sizeof(fmt));
3160 fmt.italic = italic;
3161 fmt.cs.italic = TRUE;
3163 if (underline_set) {
3164 fmt.underline = underline;
3165 fmt.cs.underline = TRUE;
3167 if (strikethrough_set) {
3168 fmt.strikethrough = strikethrough;
3169 fmt.cs.strikethrough = TRUE;
3174 ? TEXT_POSITION_NORMAL
3175 : ( ( position == 1 )
3176 ? TEXT_POSITION_SUPERSCRIPT
3177 : TEXT_POSITION_SUBSCRIPT );
3178 fmt.cs.text_position = TRUE;
3179 fmt.font_size = oldfmt.font_size;
3183 fmt.cs.color = TRUE;
3186 fmt.font = wp_get_font_index(font_name,
3191 if (font_size_set) {
3192 fmt.cs.font_size = TRUE;
3193 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3195 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3196 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3198 gtk_widget_destroy (dialog);
3200 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3204 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3206 ModestMsgEditWindowPrivate *priv;
3208 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3209 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3211 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3213 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3214 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3218 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3220 ModestMsgEditWindowPrivate *priv;
3222 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3223 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3225 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3227 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3228 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3233 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3235 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3237 priv->can_undo = can_undo;
3241 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3243 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3245 priv->can_redo = can_redo;
3249 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3251 ModestMsgEditWindowPrivate *priv;
3252 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3253 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3255 return priv->can_undo;
3259 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3261 ModestMsgEditWindowPrivate *priv;
3262 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3263 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3265 return priv->can_redo;
3270 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3273 GtkTextIter match_start, match_end;
3275 if (image_id == NULL)
3278 gtk_text_buffer_get_start_iter (buffer, &iter);
3280 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3281 GSList *tags = gtk_text_iter_get_tags (&match_start);
3283 for (node = tags; node != NULL; node = g_slist_next (node)) {
3284 GtkTextTag *tag = (GtkTextTag *) node->data;
3285 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3286 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3287 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3289 offset = gtk_text_iter_get_offset (&match_start);
3290 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3291 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3295 gtk_text_iter_forward_char (&iter);
3300 message_is_empty (ModestMsgEditWindow *window)
3302 ModestMsgEditWindowPrivate *priv = NULL;
3304 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3305 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3307 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3308 * so we can ignore markup.
3310 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3313 count = gtk_text_buffer_get_char_count (buf);
3319 msg_body_focus (GtkWidget *focus,
3320 GdkEventFocus *event,
3324 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3325 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3326 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3331 recpt_field_changed (GtkTextBuffer *buffer,
3332 ModestMsgEditWindow *editor)
3334 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3335 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3339 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3341 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3342 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3346 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3349 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3350 GtkTextBuffer *buffer;
3352 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3353 gtk_text_buffer_set_modified (buffer, modified);
3354 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3355 gtk_text_buffer_set_modified (buffer, modified);
3356 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3357 gtk_text_buffer_set_modified (buffer, modified);
3358 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3362 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3364 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3365 const char *account_name;
3366 GtkTextBuffer *buffer;
3368 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3369 if (gtk_text_buffer_get_modified (buffer))
3371 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3372 if (gtk_text_buffer_get_modified (buffer))
3374 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3375 if (gtk_text_buffer_get_modified (buffer))
3377 if (gtk_text_buffer_get_modified (priv->text_buffer))
3380 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3381 if (priv->original_mailbox) {
3382 if (!account_name || strcmp (account_name, priv->original_mailbox))
3384 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3395 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3397 ModestMsgEditWindowPrivate *priv = NULL;
3399 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3400 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3402 /* check if there's no recipient added */
3403 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3404 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3405 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3406 /* no recipient contents, then select contacts */
3407 modest_msg_edit_window_open_addressbook (window, NULL);
3411 g_object_ref (window);
3412 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3413 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3414 g_object_unref (window);
3417 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3418 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3419 g_object_unref (window);
3422 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3423 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3424 g_object_unref (window);
3428 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3429 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3430 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3431 g_object_unref (window);
3438 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3439 ModestMsgEditWindow *window)
3441 modest_msg_edit_window_offer_attach_file (window);
3445 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3447 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3449 return priv->clipboard_text;
3453 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3455 ModestMsgEditWindow *window)
3457 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3458 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3461 /* It could happen that the window was already closed */
3462 if (!GTK_WIDGET_VISIBLE (window))
3465 g_object_ref (window);
3466 text = gtk_clipboard_wait_for_text (selection_clipboard);
3468 if (priv->clipboard_text != NULL) {
3469 g_free (priv->clipboard_text);
3471 priv->clipboard_text = text;
3473 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3475 g_object_unref (window);
3478 static gboolean clipboard_owner_change_idle (gpointer userdata)
3480 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3481 ModestMsgEditWindowPrivate *priv;
3483 gdk_threads_enter ();
3484 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3485 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3487 priv->clipboard_owner_idle = 0;
3488 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3489 gdk_threads_leave ();
3495 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3497 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3498 if (priv->clipboard_owner_idle == 0) {
3499 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3500 clipboard_owner_change_idle,
3501 g_object_ref (window),
3507 subject_field_move_cursor (GtkEntry *entry,
3508 GtkMovementStep step,
3513 /* It could happen that the window was already closed */
3514 if (!GTK_WIDGET_VISIBLE (window))
3517 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3521 update_window_title (ModestMsgEditWindow *window)
3523 ModestMsgEditWindowPrivate *priv = NULL;
3524 const gchar *subject;
3526 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3527 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3528 if (subject == NULL || subject[0] == '\0')
3529 subject = _("mail_va_new_email");
3531 gtk_window_set_title (GTK_WINDOW (window), subject);
3537 body_insert_text (GtkTextBuffer *buffer,
3538 GtkTextIter *location,
3541 ModestMsgEditWindow *window)
3543 GtkTextIter end_iter;
3547 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3549 offset = gtk_text_iter_get_offset (&end_iter);
3550 utf8_len = g_utf8_strlen (text, len);
3552 if (offset + utf8_len > MAX_BODY_LENGTH) {
3553 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3554 if (offset < MAX_BODY_LENGTH)
3559 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3561 /* Prevent endless recursion */
3562 result = g_strndup (text, utf8_end - text);
3563 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3564 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3565 (gpointer) result, (gpointer) (utf8_end - text),
3567 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3571 if (offset + utf8_len > MAX_BODY_LENGTH) {
3572 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3573 _CS("ckdg_ib_maximum_characters_reached"));
3578 subject_field_changed (GtkEditable *editable,
3579 ModestMsgEditWindow *window)
3581 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3582 update_window_title (window);
3583 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3584 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3585 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3588 subject_field_insert_text (GtkEditable *editable,
3590 gint new_text_length,
3592 ModestMsgEditWindow *window)
3594 GString *result = g_string_new ("");
3596 gint result_len = 0;
3597 const gchar *entry_text = NULL;
3600 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3601 old_length = g_utf8_strlen (entry_text, -1);
3603 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3604 gunichar c = g_utf8_get_char_validated (current, 8);
3605 /* Invalid unichar, stop */
3611 result = g_string_append_unichar (result, c);
3615 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3616 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3619 /* Prevent endless recursion */
3620 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3621 g_signal_emit_by_name (editable, "insert-text",
3622 (gpointer) result->str, (gpointer) result->len,
3623 (gpointer) position, (gpointer) window);
3624 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3628 if (result_len + old_length > 1000) {
3629 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3630 _CS("ckdg_ib_maximum_characters_reached"));
3632 g_string_free (result, TRUE);
3636 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3639 ModestMsgEditWindowPrivate *priv = NULL;
3641 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3642 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3644 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3647 gtk_widget_show_all (priv->find_toolbar);
3648 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3650 gtk_widget_hide_all (priv->find_toolbar);
3651 gtk_widget_grab_focus (priv->msg_body);
3656 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3658 GtkTextIter *match_start,
3659 GtkTextIter *match_end)
3661 GtkTextIter end_iter;
3662 gchar *str_casefold;
3665 gchar *range_casefold;
3668 gboolean result = FALSE;
3675 gtk_text_iter_forward_to_end (&end_iter);
3677 str_casefold = g_utf8_casefold (str, -1);
3678 str_chars_n = strlen (str);
3680 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3681 range_casefold = g_utf8_casefold (range_text, -1);
3682 range_chars_n = strlen (range_casefold);
3684 if (range_chars_n < str_chars_n) {
3685 g_free (str_casefold);
3686 g_free (range_text);
3687 g_free (range_casefold);
3691 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3692 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3693 if (!g_utf8_collate (range_subtext, str_casefold)) {
3694 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3696 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3697 match_start, match_end, NULL)) {
3698 g_warning ("Matched string with collate, but not matched in model");
3700 g_free (found_text);
3702 g_free (range_subtext);
3706 g_free (str_casefold);
3707 g_free (range_text);
3708 g_free (range_casefold);
3715 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3716 ModestMsgEditWindow *window)
3718 gchar *current_search = NULL;
3719 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3721 GtkTextIter selection_start, selection_end;
3722 GtkTextIter match_start, match_end;
3723 gboolean continue_search = FALSE;
3725 if (message_is_empty (window)) {
3726 g_free (priv->last_search);
3727 priv->last_search = NULL;
3728 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3732 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3733 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3734 g_free (current_search);
3735 g_free (priv->last_search);
3736 priv->last_search = NULL;
3737 /* Information banner about empty search */
3738 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3742 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3743 continue_search = TRUE;
3745 g_free (priv->last_search);
3746 priv->last_search = g_strdup (current_search);
3749 if (continue_search) {
3750 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3751 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3752 &match_start, &match_end);
3754 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3756 GtkTextIter buffer_start;
3757 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3758 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3759 &match_start, &match_end);
3761 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3764 /* Mark as selected the string found in search */
3766 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3767 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3768 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3770 g_free (priv->last_search);
3771 priv->last_search = NULL;
3773 g_free (current_search);
3777 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3779 ModestMsgEditWindowPrivate *priv;
3781 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3786 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3789 ModestMsgEditWindowPrivate *priv;
3791 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3796 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3797 ModestMsgEditWindow *window)
3799 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3803 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3806 ModestMsgEditWindowPrivate *priv;
3807 TnyHeader *header = NULL;
3809 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3810 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3812 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3814 if (priv->draft_msg != NULL) {
3815 g_object_unref (priv->draft_msg);
3818 if (draft != NULL) {
3819 g_object_ref (draft);
3820 header = tny_msg_get_header (draft);
3821 if (priv->msg_uid) {
3822 g_free (priv->msg_uid);
3823 priv->msg_uid = NULL;
3825 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3828 priv->draft_msg = draft;
3832 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3833 GtkTextIter *start, GtkTextIter *end,
3836 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3837 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3840 if (tag == NULL) return;
3841 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3842 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3843 replace_with_images (window, priv->images);
3848 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3851 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3853 g_return_if_fail (TNY_IS_MIME_PART (part));
3854 tny_list_prepend (priv->attachments, (GObject *) part);
3855 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3856 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3857 gtk_widget_show_all (priv->attachments_caption);
3858 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3862 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3864 ModestMsgEditWindowPrivate *priv;
3866 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3867 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3869 return priv->msg_uid;
3873 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3874 ModestMsgEditWindowWidgetType widget_type)
3876 ModestMsgEditWindowPrivate *priv;
3878 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3879 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3881 switch (widget_type) {
3882 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3883 return priv->msg_body;
3885 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3886 return priv->to_field;
3888 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3889 return priv->cc_field;
3891 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3892 return priv->bcc_field;
3894 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3895 return priv->subject_field;
3897 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3898 return priv->attachments_view;
3906 remove_tags (WPTextBuffer *buffer)
3908 GtkTextIter start, end;
3910 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3911 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3913 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3917 on_account_removed (TnyAccountStore *account_store,
3918 TnyAccount *account,
3921 /* Do nothing if it's a store account, because we use the
3922 transport to send the messages */
3923 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3924 const gchar *parent_acc = NULL;
3925 const gchar *our_acc = NULL;
3927 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3928 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3929 /* Close this window if I'm showing a message of the removed account */
3930 if (strcmp (parent_acc, our_acc) == 0)
3931 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3935 static void update_signature (ModestMsgEditWindow *self,
3936 const gchar *old_account,
3937 const gchar *new_account)
3939 ModestMsgEditWindowPrivate *priv;
3940 gboolean has_old_signature, has_new_signature;
3942 GtkTextIter match_start, match_end;
3943 ModestAccountMgr *mgr;
3945 gchar *full_signature;
3947 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3949 gtk_text_buffer_begin_user_action (priv->text_buffer);
3951 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3952 mgr = modest_runtime_get_account_mgr ();
3956 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
3957 if (has_old_signature) {
3958 full_signature = g_strconcat ("\n--\n", signature, NULL);
3959 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3960 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3962 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3963 &match_start, &match_end, NULL)) {
3966 g_free (full_signature);
3971 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3972 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
3973 if (has_new_signature) {
3974 full_signature = g_strconcat ("\n--\n", signature, NULL);
3975 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3976 g_free (full_signature);
3979 gtk_text_buffer_end_user_action (priv->text_buffer);
3983 from_field_changed (HildonPickerButton *button,
3984 ModestMsgEditWindow *self)
3986 ModestMsgEditWindowPrivate *priv;
3987 gchar *old_account, *new_account;
3989 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3991 old_account = priv->last_from_account;
3992 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3993 new_account = priv->last_from_account;
3995 update_signature (self, old_account, new_account);
3999 typedef struct _MessageSettingsHelper {
4000 ModestMsgEditWindow *window;
4001 GSList *priority_group;
4002 GSList *format_group;
4003 GtkToggleButton *current_priority;
4004 GtkToggleButton *current_format;
4005 } MessageSettingsHelper;
4008 on_priority_toggle (GtkToggleButton *button,
4009 MessageSettingsHelper *helper)
4012 ModestMsgEditWindowPrivate *priv;
4014 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4015 if (gtk_toggle_button_get_active (button)) {
4017 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4018 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4019 if ((node_button != button) &&
4020 gtk_toggle_button_get_active (node_button)) {
4021 gtk_toggle_button_set_active (node_button, FALSE);
4024 helper->current_priority = button;
4026 gboolean found = FALSE;
4027 /* If no one is active, activate it again */
4028 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4029 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4030 if (gtk_toggle_button_get_active (node_button)) {
4036 gtk_toggle_button_set_active (button, TRUE);
4042 on_format_toggle (GtkToggleButton *button,
4043 MessageSettingsHelper *helper)
4046 ModestMsgEditWindowPrivate *priv;
4048 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4049 if (gtk_toggle_button_get_active (button)) {
4051 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4052 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4053 if ((node_button != button) &&
4054 gtk_toggle_button_get_active (node_button)) {
4055 gtk_toggle_button_set_active (node_button, FALSE);
4058 helper->current_format = button;
4060 gboolean found = FALSE;
4061 /* If no one is active, activate it again */
4062 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4063 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4064 if (gtk_toggle_button_get_active (node_button)) {
4070 gtk_toggle_button_set_active (button, TRUE);
4077 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4082 GtkWidget *priority_hbox;
4083 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4084 GtkWidget *captioned;
4085 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4086 GtkWidget *format_hbox;
4087 GtkWidget *html_toggle, *text_toggle;
4088 ModestMsgEditWindowPrivate *priv;
4089 MessageSettingsHelper helper = {0,};
4091 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4092 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4093 helper.window = window;
4094 helper.priority_group = NULL;
4095 helper.format_group = NULL;
4097 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4098 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4100 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4101 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4102 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4103 vbox = gtk_vbox_new (FALSE, 0);
4104 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4105 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4106 gtk_container_add (GTK_CONTAINER (align), vbox);
4107 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4108 gtk_widget_show (align);
4109 gtk_widget_show (vbox);
4111 /* Priority toggles */
4112 priority_hbox = gtk_hbox_new (TRUE, 0);
4113 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4114 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4115 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4116 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4117 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4118 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4119 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4120 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4121 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4122 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4123 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4124 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4125 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4126 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4127 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4128 gtk_widget_show_all (priority_hbox);
4129 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4130 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4131 gtk_widget_show (captioned);
4132 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4134 /* format toggles */
4135 format_hbox = gtk_hbox_new (TRUE, 0);
4136 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4137 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4138 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4139 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4140 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4141 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4142 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4143 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4144 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4145 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4146 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4147 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4148 gtk_widget_show_all (format_hbox);
4149 gtk_widget_show (format_hbox);
4150 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4153 g_object_unref (title_sizegroup);
4154 g_object_unref (value_sizegroup);
4156 /* Set current values */
4157 switch (priv->priority_flags) {
4158 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4159 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4160 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4162 case TNY_HEADER_FLAG_LOW_PRIORITY:
4163 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4164 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4167 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4168 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4172 switch (modest_msg_edit_window_get_format (window)) {
4173 case MODEST_MSG_EDIT_FORMAT_TEXT:
4174 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4175 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4177 case MODEST_MSG_EDIT_FORMAT_HTML:
4179 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4180 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4184 /* Signal connects */
4185 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4186 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4187 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4188 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4189 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4191 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4192 GTK_WINDOW (dialog), GTK_WINDOW (window));
4194 /* Save settings if the user clicked on done */
4195 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4196 TnyHeaderFlags flags;
4197 ModestMsgEditFormat old_format, new_format;
4199 /* Set priority flags */
4200 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4201 if (priv->priority_flags != flags)
4202 modest_msg_edit_window_set_priority_flags (window, flags);
4204 /* Set edit format */
4205 old_format = modest_msg_edit_window_get_format (window);
4206 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4207 if (old_format != new_format) {
4208 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4209 modest_msg_edit_window_set_file_format (window, file_format);
4213 gtk_widget_destroy (dialog);
4214 g_slist_free (helper.priority_group);
4218 on_message_settings (GtkAction *action,
4219 ModestMsgEditWindow *window)
4221 modest_msg_edit_window_show_msg_settings_dialog (window);
4225 on_cc_button_toggled (HildonCheckButton *button,
4226 ModestMsgEditWindow *window)
4228 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4230 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4231 hildon_check_button_get_active (button));
4235 on_bcc_button_toggled (HildonCheckButton *button,
4236 ModestMsgEditWindow *window)
4238 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4240 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4241 hildon_check_button_get_active (button));
4245 setup_menu (ModestMsgEditWindow *self)
4247 ModestMsgEditWindowPrivate *priv = NULL;
4249 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4251 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4253 /* Settings menu buttons */
4254 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4255 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4257 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4258 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4259 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4261 priv->cc_button = hildon_check_button_new (0);
4262 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4263 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4265 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4267 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4268 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4269 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4270 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4272 priv->bcc_button = hildon_check_button_new (0);
4273 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4274 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4276 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4278 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4279 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4280 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4281 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4283 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4284 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4285 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4286 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4287 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4289 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4290 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4291 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4292 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4293 APP_MENU_CALLBACK (on_message_settings),
4295 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4296 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4301 emit_open_addressbook (GtkButton *button,
4302 ModestRecptEditor *editor)
4304 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4308 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4309 const gchar *label, GtkWidget *control)
4311 GtkWidget *abook_button;
4314 GtkWidget *label_widget;
4316 box = gtk_hbox_new (FALSE, 0);
4318 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4319 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4321 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4322 label_widget = gtk_label_new (label);
4323 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4324 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4326 gtk_container_add (GTK_CONTAINER (align), abook_button);
4327 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4328 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4329 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4330 if (title_size_group)
4331 gtk_size_group_add_widget (title_size_group, label_widget);
4332 if (value_size_group)
4333 gtk_size_group_add_widget (value_size_group, control);
4335 g_signal_connect (G_OBJECT (abook_button), "clicked",
4336 G_CALLBACK (emit_open_addressbook), control);