1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
42 #include <modest-account-mgr.h>
43 #include <modest-account-mgr-helpers.h>
45 #include <widgets/modest-msg-edit-window.h>
46 #include <modest-selector-picker.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <modest-wp-text-view.h>
65 #include <wptextbuffer.h>
66 #include <hildon/hildon-pannable-area.h>
67 #include <hildon/hildon-touch-selector.h>
68 #include <hildon/hildon-picker-dialog.h>
69 #include "modest-msg-edit-window-ui-dimming.h"
71 #include "modest-hildon-includes.h"
72 #ifdef MODEST_HAVE_HILDON0_WIDGETS
73 #include <hildon-widgets/hildon-color-chooser.h>
75 #include "widgets/modest-msg-edit-window-ui.h"
76 #ifdef MODEST_HAVE_HILDON0_WIDGETS
77 #include <libgnomevfs/gnome-vfs-mime-utils.h>
79 #include <libgnomevfs/gnome-vfs-mime.h>
81 #include <modest-utils.h>
82 #include "modest-maemo-utils.h"
83 #include <modest-ui-constants.h>
86 #define DEFAULT_FONT_SIZE 3
87 #define DEFAULT_FONT 2
88 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
89 #define DEFAULT_MAIN_VBOX_SPACING 6
90 #define SUBJECT_MAX_LENGTH 1000
91 #define IMAGE_MAX_WIDTH 560
92 #define DEFAULT_FONT_SCALE 1.5
93 #define ATTACHMENT_BUTTON_WIDTH 118
95 static gboolean is_wp_text_buffer_started = FALSE;
97 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
98 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
99 static void modest_msg_edit_window_finalize (GObject *obj);
101 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
102 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
103 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
105 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
106 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
107 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
108 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
109 GtkTextIter *start, GtkTextIter *end,
111 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
112 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
113 static void subject_field_insert_text (GtkEditable *editable,
115 gint new_text_length,
117 ModestMsgEditWindow *window);
118 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
120 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
122 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
123 ModestRecptEditor *editor);
124 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
125 ModestMsgEditWindow *window);
127 /* ModestWindow methods implementation */
128 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
129 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
130 gboolean show_toolbar);
131 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
133 ModestMsgEditWindow *window);
134 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
135 static void subject_field_move_cursor (GtkEntry *entry,
136 GtkMovementStep step,
140 static void update_window_title (ModestMsgEditWindow *window);
143 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
144 ModestMsgEditWindow *window);
145 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
146 ModestMsgEditWindow *window);
147 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
149 GtkTextIter *match_start,
150 GtkTextIter *match_end);
152 static void remove_tags (WPTextBuffer *buffer);
154 static void on_account_removed (TnyAccountStore *account_store,
158 static void init_window (ModestMsgEditWindow *obj);
160 gboolean scroll_drag_timeout (gpointer userdata);
161 static void correct_scroll (ModestMsgEditWindow *w);
162 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
163 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
164 ModestMsgEditWindow *userdata);
165 static void text_buffer_mark_set (GtkTextBuffer *buffer,
168 ModestMsgEditWindow *userdata);
169 static void on_message_settings (GtkAction *action,
170 ModestMsgEditWindow *window);
171 static void setup_menu (ModestMsgEditWindow *self);
173 static void from_field_changed (HildonPickerButton *button,
174 ModestMsgEditWindow *self);
175 static void font_size_clicked (GtkToolButton *button,
176 ModestMsgEditWindow *window);
177 static void font_face_clicked (GtkToolButton *button,
178 ModestMsgEditWindow *window);
179 static void DEBUG_BUFFER (WPTextBuffer *buffer)
183 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
185 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
186 while (!gtk_text_iter_is_end (&iter)) {
187 GString *output = g_string_new ("");
188 GSList *toggled_tags;
191 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
192 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
193 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
194 GtkTextTag *tag = (GtkTextTag *) node->data;
196 g_object_get (G_OBJECT (tag), "name", &name, NULL);
197 output = g_string_append (output, name);
198 g_string_append (output, " ");
200 output = g_string_append (output, "] OPENED [ ");
201 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
202 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
203 GtkTextTag *tag = (GtkTextTag *) node->data;
205 g_object_get (G_OBJECT (tag), "name", &name, NULL);
206 output = g_string_append (output, name);
207 g_string_append (output, " ");
209 output = g_string_append (output, "]\n");
210 g_message ("%s", output->str);
211 g_string_free (output, TRUE);
212 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
214 g_message ("END BUFFER");
218 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
219 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
223 /* static gboolean */
224 /* on_key_pressed (GtkWidget *self, */
225 /* GdkEventKey *event, */
226 /* gpointer user_data); */
228 /* list my signals */
235 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
236 struct _ModestMsgEditWindowPrivate {
238 GtkWidget *header_box;
240 ModestPairList *from_field_protos;
241 GtkWidget *from_field;
242 gchar *last_from_account;
243 gchar *original_account_name;
248 gchar *original_mailbox;
252 GtkWidget *bcc_field;
253 GtkWidget *subject_field;
254 GtkWidget *attachments_view;
255 GtkWidget *priority_icon;
256 GtkWidget *subject_box;
257 GtkWidget *add_attachment_button;
259 GtkWidget *cc_caption;
260 GtkWidget *bcc_caption;
261 gboolean update_caption_visibility;
262 GtkWidget *attachments_caption;
264 GtkTextBuffer *text_buffer;
266 GtkWidget *font_size_toolitem;
267 GtkWidget *font_face_toolitem;
268 GtkWidget *font_color_button;
269 GtkWidget *font_color_toolitem;
270 GSList *font_items_group;
271 GtkTreeModel *faces_model;
272 gint current_face_index;
273 GtkWidget *font_tool_button_label;
274 GtkTreeModel *sizes_model;
275 gint current_size_index;
276 GtkWidget *size_tool_button_label;
278 GtkWidget *find_toolbar;
281 GtkWidget *font_dialog;
284 guint correct_scroll_idle;
285 guint scroll_drag_timeout_id;
289 TnyList *attachments;
294 TnyHeaderFlags priority_flags;
296 gboolean can_undo, can_redo;
297 gulong clipboard_change_handler_id;
298 gulong default_clipboard_change_handler_id;
299 gulong account_removed_handler_id;
300 guint clipboard_owner_idle;
301 gchar *clipboard_text;
310 GtkWidget *cc_button;
311 GtkWidget *bcc_button;
314 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
315 MODEST_TYPE_MSG_EDIT_WINDOW, \
316 ModestMsgEditWindowPrivate))
318 static GtkWindowClass *parent_class = NULL;
320 /* uncomment the following if you have defined any signals */
321 /* static guint signals[LAST_SIGNAL] = {0}; */
324 modest_msg_edit_window_get_type (void)
326 static GType my_type = 0;
328 static const GTypeInfo my_info = {
329 sizeof(ModestMsgEditWindowClass),
330 NULL, /* base init */
331 NULL, /* base finalize */
332 (GClassInitFunc) modest_msg_edit_window_class_init,
333 NULL, /* class finalize */
334 NULL, /* class data */
335 sizeof(ModestMsgEditWindow),
337 (GInstanceInitFunc) modest_msg_edit_window_init,
340 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
341 "ModestMsgEditWindow",
349 save_state (ModestWindow *self)
351 modest_widget_memory_save (modest_runtime_get_conf(),
352 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
357 restore_settings (ModestMsgEditWindow *self)
359 ModestConf *conf = NULL;
361 conf = modest_runtime_get_conf ();
363 /* Dim at start clipboard actions */
364 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
369 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
371 GObjectClass *gobject_class;
372 ModestWindowClass *modest_window_class;
373 gobject_class = (GObjectClass*) klass;
374 modest_window_class = (ModestWindowClass*) klass;
376 parent_class = g_type_class_peek_parent (klass);
377 gobject_class->finalize = modest_msg_edit_window_finalize;
379 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
380 modest_window_class->save_state_func = save_state;
381 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
383 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
387 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
389 ModestMsgEditWindowPrivate *priv;
390 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
392 priv->msg_body = NULL;
393 priv->from_field = NULL;
394 priv->to_field = NULL;
395 priv->cc_field = NULL;
396 priv->bcc_field = NULL;
397 priv->subject_field = NULL;
398 priv->attachments = TNY_LIST (tny_simple_list_new ());
399 priv->images = TNY_LIST (tny_simple_list_new ());
400 priv->images_size = 0;
401 priv->images_count = 0;
404 priv->cc_caption = NULL;
405 priv->bcc_caption = NULL;
406 priv->update_caption_visibility = FALSE;
408 priv->priority_flags = 0;
410 priv->find_toolbar = NULL;
411 priv->last_search = NULL;
413 priv->draft_msg = NULL;
414 priv->outbox_msg = NULL;
415 priv->msg_uid = NULL;
417 priv->can_undo = FALSE;
418 priv->can_redo = FALSE;
419 priv->clipboard_change_handler_id = 0;
420 priv->default_clipboard_change_handler_id = 0;
421 priv->account_removed_handler_id = 0;
422 priv->clipboard_owner_idle = 0;
423 priv->clipboard_text = NULL;
426 priv->scroll_drag_timeout_id = 0;
427 priv->correct_scroll_idle = 0;
428 priv->last_upper = 0.0;
430 priv->font_dialog = NULL;
431 priv->app_menu = NULL;
433 priv->references = NULL;
434 priv->in_reply_to = NULL;
436 if (!is_wp_text_buffer_started) {
437 is_wp_text_buffer_started = TRUE;
438 wp_text_buffer_library_init ();
443 hildon_program_add_window (hildon_program_get_instance(),
449 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
451 static ModestPairList*
452 get_transports (void)
454 GSList *transports = NULL;
456 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
457 GSList *accounts = modest_account_mgr_account_names (account_mgr,
458 TRUE /* only enabled accounts. */);
460 GSList *cursor = accounts;
462 gchar *account_name = cursor->data;
463 gchar *from_string = NULL;
465 from_string = modest_account_mgr_get_from_string (account_mgr,
469 if (from_string && account_name) {
470 gchar *name = account_name;
471 ModestPair *pair = modest_pair_new ((gpointer) name,
472 (gpointer) from_string , TRUE);
473 transports = g_slist_prepend (transports, pair);
476 cursor = cursor->next;
478 g_slist_free (accounts); /* only free the accounts, not the elements,
479 * because they are used in the pairlist */
483 static void window_focus (GtkWindow *window,
487 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
491 scroll_drag_timeout (gpointer userdata)
493 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
494 ModestMsgEditWindowPrivate *priv;
496 /* It could happen that the window was already closed */
497 if (!GTK_WIDGET_VISIBLE (win))
500 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
502 correct_scroll_without_drag_check (win, TRUE);
504 priv->scroll_drag_timeout_id = 0;
510 correct_scroll_without_drag_check_idle (gpointer userdata)
512 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
513 ModestMsgEditWindowPrivate *priv;
515 GdkRectangle rectangle;
516 gint offset_min, offset_max;
520 /* It could happen that the window was already closed */
521 if (!GTK_WIDGET_VISIBLE (w))
524 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
526 insert = gtk_text_buffer_get_insert (priv->text_buffer);
527 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
529 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
530 offset_min = priv->msg_body->allocation.y + rectangle.y;
531 offset_max = offset_min + rectangle.height;
533 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
534 offset_min = MAX (offset_min - 48, 0);
535 offset_max = MIN (offset_max + 48, vadj->upper);
537 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
539 priv->correct_scroll_idle = 0;
544 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
546 ModestMsgEditWindowPrivate *priv;
548 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
550 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
553 if (priv->correct_scroll_idle > 0) {
557 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
558 (GSourceFunc) correct_scroll_without_drag_check_idle,
564 correct_scroll (ModestMsgEditWindow *w)
566 ModestMsgEditWindowPrivate *priv;
568 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
569 if (gtk_grab_get_current () == priv->msg_body) {
570 if (priv->scroll_drag_timeout_id == 0) {
571 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
573 (GSourceFunc) scroll_drag_timeout,
580 correct_scroll_without_drag_check (w, TRUE);
584 text_buffer_end_user_action (GtkTextBuffer *buffer,
585 ModestMsgEditWindow *userdata)
588 correct_scroll (userdata);
592 text_buffer_mark_set (GtkTextBuffer *buffer,
595 ModestMsgEditWindow *userdata)
597 gtk_text_buffer_begin_user_action (buffer);
598 gtk_text_buffer_end_user_action (buffer);
602 cut_clipboard_check (GtkTextView *text_view,
605 GtkTextBuffer *buffer;
607 buffer = gtk_text_view_get_buffer (text_view);
608 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
609 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
614 copy_clipboard_check (GtkTextView *text_view,
617 GtkTextBuffer *buffer;
619 buffer = gtk_text_view_get_buffer (text_view);
620 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
621 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
626 attachment_deleted (ModestAttachmentsView *attachments_view,
629 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
634 connect_signals (ModestMsgEditWindow *obj)
636 ModestMsgEditWindowPrivate *priv;
638 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
640 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
641 G_CALLBACK (text_buffer_refresh_attributes), obj);
642 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
643 G_CALLBACK (text_buffer_can_undo), obj);
644 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
645 G_CALLBACK (text_buffer_can_redo), obj);
646 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
647 G_CALLBACK (body_changed), obj);
648 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
649 G_CALLBACK (body_changed), obj);
650 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
651 G_CALLBACK (text_buffer_end_user_action), obj);
652 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
653 G_CALLBACK (text_buffer_mark_set), obj);
654 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
655 G_CALLBACK (text_buffer_apply_tag), obj);
656 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
657 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
658 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
659 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
660 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
661 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
663 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
664 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
665 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
666 G_CALLBACK (from_field_changed), obj);
668 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
669 G_CALLBACK (msg_body_focus), obj);
670 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
671 G_CALLBACK (msg_body_focus), obj);
672 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
673 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
674 "changed", G_CALLBACK (recpt_field_changed), obj);
675 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
676 "changed", G_CALLBACK (recpt_field_changed), obj);
677 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
678 "changed", G_CALLBACK (recpt_field_changed), obj);
679 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
680 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
681 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
683 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
684 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
686 priv->clipboard_change_handler_id =
687 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
688 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
689 priv->default_clipboard_change_handler_id =
690 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
691 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
693 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
694 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
695 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
699 init_wp_text_view_style ()
701 static gboolean initialized = FALSE;
704 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
710 init_window (ModestMsgEditWindow *obj)
712 GtkWidget *to_caption, *subject_caption;
713 GtkWidget *main_vbox;
714 GtkWidget *add_attachment_align;
715 ModestMsgEditWindowPrivate *priv;
716 GtkActionGroup *action_group;
717 ModestWindowPrivate *parent_priv;
718 GdkPixbuf *window_icon = NULL;
719 GError *error = NULL;
721 GtkSizeGroup *title_size_group;
722 GtkSizeGroup *value_size_group;
723 GtkWidget *attachment_icon;
724 GtkWidget *window_box;
725 GtkWidget *window_align;
726 #if (GTK_MINOR_VERSION >= 10)
727 GdkAtom deserialize_type;
730 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
731 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
733 parent_priv->ui_manager = gtk_ui_manager_new();
734 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
735 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
737 /* Add common actions */
738 gtk_action_group_add_actions (action_group,
739 modest_msg_edit_action_entries,
740 G_N_ELEMENTS (modest_msg_edit_action_entries),
742 gtk_action_group_add_actions (action_group,
743 hildon2_msg_edit_action_entries,
744 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
746 gtk_action_group_add_toggle_actions (action_group,
747 modest_msg_edit_toggle_action_entries,
748 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
750 gtk_action_group_add_radio_actions (action_group,
751 modest_msg_edit_alignment_radio_action_entries,
752 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
754 G_CALLBACK (modest_ui_actions_on_change_justify),
756 gtk_action_group_add_radio_actions (action_group,
757 modest_msg_edit_priority_action_entries,
758 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
760 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
762 gtk_action_group_add_radio_actions (action_group,
763 modest_msg_edit_file_format_action_entries,
764 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
765 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
766 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
768 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
769 g_object_unref (action_group);
771 /* Load the UI definition */
772 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
775 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
776 g_clear_error (&error);
779 /* Add accelerators */
780 gtk_window_add_accel_group (GTK_WINDOW (obj),
781 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
783 parent_priv->menubar = NULL;
785 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
786 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
788 /* Note: This ModestPairList* must exist for as long as the picker
789 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
790 * so it can't know how to manage its memory. */
791 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
792 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
794 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
795 _("mail_va_from"), priv->from_field);
797 priv->to_field = modest_recpt_editor_new ();
798 priv->cc_field = modest_recpt_editor_new ();
799 priv->bcc_field = modest_recpt_editor_new ();
800 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
801 priv->priority_icon = gtk_image_new ();
802 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
803 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
804 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
805 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
806 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
807 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
808 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
809 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
810 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
811 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
812 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
813 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
814 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
815 add_attachment_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
816 gtk_alignment_set_padding (GTK_ALIGNMENT (add_attachment_align), 0, 0, MODEST_MARGIN_DEFAULT, 0);
817 gtk_container_add (GTK_CONTAINER (add_attachment_align), priv->add_attachment_button);
818 gtk_box_pack_start (GTK_BOX (priv->subject_box), add_attachment_align, FALSE, FALSE, 0);
819 priv->attachments_view = modest_attachments_view_new (NULL);
820 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
821 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
823 priv->header_box = gtk_vbox_new (FALSE, 0);
825 to_caption = modest_maemo_utils_create_captioned_with_size_type
826 (title_size_group, value_size_group,
827 _("mail_va_to"), FALSE, priv->to_field,
828 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
829 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
830 (title_size_group, value_size_group,
831 _("mail_va_cc"), FALSE, priv->cc_field,
832 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
833 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
834 (title_size_group, value_size_group,
835 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
836 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
837 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
838 _("mail_va_subject"), FALSE, priv->subject_box);
839 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
840 _("mail_va_attachment"),
842 priv->attachments_view,
843 HILDON_SIZE_AUTO_WIDTH |
844 HILDON_SIZE_AUTO_HEIGHT);
845 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
846 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
847 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
848 g_object_unref (title_size_group);
849 g_object_unref (value_size_group);
851 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
852 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
853 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
854 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
855 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
856 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
857 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
859 init_wp_text_view_style ();
861 priv->msg_body = modest_wp_text_view_new ();
864 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
865 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
866 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
867 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
868 #if (GTK_MINOR_VERSION >= 10)
869 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
870 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
872 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
873 deserialize_type, TRUE);
875 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
877 priv->find_toolbar = hildon_find_toolbar_new (NULL);
878 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
880 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
882 priv->pannable = hildon_pannable_area_new ();
884 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
885 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
886 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
888 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
889 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
890 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
892 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
893 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
895 window_box = gtk_vbox_new (FALSE, 0);
896 gtk_container_add (GTK_CONTAINER(obj), window_box);
898 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
900 /* Set window icon */
901 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
903 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
904 g_object_unref (window_icon);
909 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
911 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
913 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
914 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
915 priv->clipboard_change_handler_id))
916 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
917 priv->clipboard_change_handler_id);
918 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
919 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
920 priv->default_clipboard_change_handler_id))
921 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
922 priv->default_clipboard_change_handler_id);
924 if (priv->account_removed_handler_id &&
925 g_signal_handler_is_connected (modest_runtime_get_account_store (),
926 priv->account_removed_handler_id))
927 g_signal_handler_disconnect(modest_runtime_get_account_store (),
928 priv->account_removed_handler_id);
932 modest_msg_edit_window_finalize (GObject *obj)
934 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
936 /* Sanity check: shouldn't be needed, the window mgr should
937 call this function before */
938 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
940 if (priv->font_dialog != NULL) {
941 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
944 if (priv->clipboard_text != NULL) {
945 g_free (priv->clipboard_text);
946 priv->clipboard_text = NULL;
949 if (priv->draft_msg != NULL) {
950 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
951 if (TNY_IS_HEADER (header)) {
952 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
953 modest_window_mgr_unregister_header (mgr, header);
955 g_object_unref (priv->draft_msg);
956 priv->draft_msg = NULL;
958 if (priv->outbox_msg != NULL) {
959 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
960 if (TNY_IS_HEADER (header)) {
961 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
962 modest_window_mgr_unregister_header (mgr, header);
964 g_object_unref (priv->outbox_msg);
965 priv->outbox_msg = NULL;
967 if (priv->correct_scroll_idle > 0) {
968 g_source_remove (priv->correct_scroll_idle);
969 priv->correct_scroll_idle = 0;
971 if (priv->scroll_drag_timeout_id > 0) {
972 g_source_remove (priv->scroll_drag_timeout_id);
973 priv->scroll_drag_timeout_id = 0;
975 if (priv->clipboard_owner_idle > 0) {
976 g_source_remove (priv->clipboard_owner_idle);
977 priv->clipboard_owner_idle = 0;
979 if (priv->original_account_name)
980 g_free (priv->original_account_name);
981 if (priv->original_mailbox)
982 g_free (priv->original_mailbox);
983 g_free (priv->msg_uid);
984 g_free (priv->last_search);
985 g_free (priv->references);
986 g_free (priv->in_reply_to);
987 g_object_unref (priv->faces_model);
988 g_object_unref (priv->sizes_model);
989 g_object_unref (priv->attachments);
990 g_object_unref (priv->images);
992 /* This had to stay alive for as long as the picker that used it: */
993 modest_pair_list_free (priv->from_field_protos);
995 G_OBJECT_CLASS(parent_class)->finalize (obj);
999 pixbuf_size_prepared (GdkPixbufLoader *loader,
1002 ModestMsgEditWindow *self)
1004 gint new_height, new_width;
1007 new_height = height;
1011 if (width > IMAGE_MAX_WIDTH) {
1012 new_height = height * IMAGE_MAX_WIDTH / width;
1013 new_width = IMAGE_MAX_WIDTH;
1016 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1020 pixbuf_from_stream (TnyStream *stream,
1021 const gchar *mime_type,
1022 guint64 *stream_size,
1023 ModestMsgEditWindow *self)
1025 GdkPixbufLoader *loader;
1028 GError *error = NULL;
1032 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1034 if (loader == NULL) {
1039 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1041 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1043 tny_stream_reset (TNY_STREAM (stream));
1044 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1045 unsigned char read_buffer[128];
1047 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1049 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1052 /* Allow some UI responsiveness */
1053 while (gtk_events_pending ())
1054 gtk_main_iteration ();
1056 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1058 gdk_pixbuf_loader_close (loader, &error);
1061 g_error_free (error);
1062 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1064 g_object_ref (pixbuf);
1065 g_object_unref (loader);
1070 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1071 GdkPixbuf *new_pixbuf;
1073 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1074 gdk_pixbuf_get_width (pixbuf);
1075 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1076 g_object_unref (pixbuf);
1077 pixbuf = new_pixbuf;
1081 *stream_size = size;
1087 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1089 ModestMsgEditWindowPrivate *priv;
1092 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1094 g_object_ref (self);
1095 for (iter = tny_list_create_iterator (attachments);
1096 !tny_iterator_is_done (iter);
1097 tny_iterator_next (iter)) {
1098 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1099 const gchar *cid = tny_mime_part_get_content_id (part);
1100 const gchar *mime_type = tny_mime_part_get_content_type (part);
1101 if ((cid != NULL)&&(mime_type != NULL)) {
1102 guint64 stream_size;
1103 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1104 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1107 g_object_unref (stream);
1109 if (pixbuf != NULL) {
1110 priv->images_count ++;
1111 priv->images_size += stream_size;
1112 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1113 g_object_unref (pixbuf);
1116 g_object_unref (part);
1118 g_object_unref (iter);
1119 g_object_unref (self);
1123 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1125 TnyMimePart *parent = NULL;
1126 const gchar *content_type = NULL;
1127 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1129 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1131 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1132 parent = g_object_ref (msg);
1133 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1134 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1137 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1138 iter = tny_list_create_iterator (parts);
1139 while (!tny_iterator_is_done (iter)) {
1141 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1142 content_type = tny_mime_part_get_content_type (part);
1143 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1147 g_object_unref (part);
1149 tny_iterator_next (iter);
1151 g_object_unref (iter);
1152 g_object_unref (parts);
1155 if (parent != NULL) {
1156 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1159 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1160 iter = tny_list_create_iterator (parts);
1161 while (!tny_iterator_is_done (iter)) {
1163 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1164 content_type = tny_mime_part_get_content_type (part);
1165 if (content_type && g_str_has_prefix (content_type, "image/")) {
1166 tny_list_prepend (priv->images, (GObject *) part);
1168 g_object_unref (part);
1169 tny_iterator_next (iter);
1171 g_object_unref (iter);
1172 g_object_unref (parts);
1173 g_object_unref (parent);
1178 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1181 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1183 for (iter = tny_list_create_iterator (attachments) ;
1184 !tny_iterator_is_done (iter);
1185 tny_iterator_next (iter)) {
1186 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1187 const gchar *cid = tny_mime_part_get_content_id (part);
1189 char *invalid = NULL;
1190 gint int_cid = strtol (cid, &invalid, 10);
1191 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1192 priv->next_cid = int_cid + 1;
1195 g_object_unref (part);
1197 g_object_unref (iter);
1201 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1204 gchar *to, *cc, *bcc, *subject;
1206 ModestMsgEditWindowPrivate *priv;
1207 ModestWindowPrivate *parent_priv;
1209 TnyHeaderFlags priority_flags;
1210 TnyFolder *msg_folder;
1211 gboolean is_html = FALSE;
1212 gboolean field_view_set;
1214 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1215 g_return_if_fail (TNY_IS_MSG (msg));
1217 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1218 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1220 header = tny_msg_get_header (msg);
1221 to = tny_header_dup_to (header);
1222 cc = tny_header_dup_cc (header);
1223 bcc = tny_header_dup_bcc (header);
1224 subject = tny_header_dup_subject (header);
1226 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1227 priority_flags = tny_header_get_priority (header);
1230 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1232 field_view_set = TRUE;
1234 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1235 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1236 gtk_widget_show (priv->cc_caption);
1237 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1238 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1239 gtk_widget_hide (priv->cc_caption);
1240 field_view_set = FALSE;
1242 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1244 field_view_set = TRUE;
1246 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1247 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1248 gtk_widget_show (priv->bcc_caption);
1249 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1250 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1251 gtk_widget_hide (priv->bcc_caption);
1252 field_view_set = FALSE;
1254 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1258 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1259 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1262 update_window_title (self);
1264 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1265 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1267 if ((body == NULL)||(body[0] == '\0')) {
1269 body = modest_text_utils_convert_to_html ("");
1272 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1273 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1276 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1279 /* Add attachments to the view */
1280 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1281 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1282 if (tny_list_get_length (priv->attachments) == 0) {
1283 gtk_widget_hide (priv->attachments_caption);
1285 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1286 gtk_widget_show_all (priv->attachments_caption);
1288 get_related_images (self, msg);
1289 update_next_cid (self, priv->attachments);
1290 update_next_cid (self, priv->images);
1291 replace_with_images (self, priv->images);
1293 if (preserve_is_rich && !is_html) {
1294 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1295 /* Get the default format required from configuration */
1296 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1297 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1300 /* Set the default focus depending on having already a To: field or not */
1301 if ((!to)||(*to == '\0')) {
1302 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1304 gtk_widget_grab_focus (priv->msg_body);
1307 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1309 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1310 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1312 modest_msg_edit_window_set_modified (self, FALSE);
1314 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1315 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1316 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1317 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1319 if (priv->msg_uid) {
1320 g_free (priv->msg_uid);
1321 priv->msg_uid = NULL;
1324 /* we should set a reference to the incoming message if it is a draft */
1325 msg_folder = tny_msg_get_folder (msg);
1327 if (modest_tny_folder_is_local_folder (msg_folder)) {
1328 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1329 if (type == TNY_FOLDER_TYPE_INVALID)
1330 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1332 if (type == TNY_FOLDER_TYPE_DRAFTS)
1333 priv->draft_msg = g_object_ref(msg);
1334 if (type == TNY_FOLDER_TYPE_OUTBOX)
1335 priv->outbox_msg = g_object_ref(msg);
1336 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1338 g_object_unref (msg_folder);
1349 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1351 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1352 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1353 GtkWidget *placeholder;
1354 GtkWidget *tool_item;
1359 GtkWidget *sizes_menu;
1360 GtkWidget *fonts_menu;
1366 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1367 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1368 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1369 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1371 /* Font color placeholder */
1372 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1373 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1376 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1377 priv->font_color_button = hildon_color_button_new ();
1378 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1379 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1380 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1381 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1382 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1383 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1384 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1385 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1387 G_CALLBACK (modest_msg_edit_window_color_button_change),
1390 /* Font size and face placeholder */
1391 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1392 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1394 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1395 priv->size_tool_button_label = gtk_label_new (NULL);
1396 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1397 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1398 size_text, "</span>", NULL);
1399 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1400 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1402 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1403 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1404 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1405 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1406 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1407 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1408 gtk_widget_set_sensitive (arrow, FALSE);
1409 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1410 sizes_menu = gtk_menu_new ();
1411 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1412 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1415 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1416 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1418 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1422 if (wp_font_size[size_index] == 12)
1423 priv->current_size_index = size_index;
1427 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1428 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1429 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1430 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1431 priv->font_size_toolitem = tool_item;
1434 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1435 priv->font_tool_button_label = gtk_label_new (NULL);
1436 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1437 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1438 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1440 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1441 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1442 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1443 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1444 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1445 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1446 gtk_widget_set_sensitive (arrow, FALSE);
1447 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1448 fonts_menu = gtk_menu_new ();
1449 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1450 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1453 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1455 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1456 0, wp_get_font_name (font_index),
1459 if (font_index == DEFAULT_FONT)
1460 priv->current_face_index = font_index;
1462 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1463 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1464 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1465 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1466 priv->font_face_toolitem = tool_item;
1468 /* Set expand and homogeneous for remaining items */
1469 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1470 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1471 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1472 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1473 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1474 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1475 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1476 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1477 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1479 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1480 will not show the tool items added to the placeholders) */
1481 gtk_widget_show_all (parent_priv->toolbar);
1483 /* Set the no show all *after* showing all items. We do not
1484 want the toolbar to be shown with a show all because it
1485 could go agains the gconf setting regarding showing or not
1486 the toolbar of the editor window */
1487 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1493 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1496 ModestWindowPrivate *parent_priv;
1497 ModestMsgEditWindowPrivate *priv;
1498 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1499 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1500 ModestWindowMgr *mgr = NULL;
1502 g_return_val_if_fail (msg, NULL);
1503 g_return_val_if_fail (account_name, NULL);
1505 mgr = modest_runtime_get_window_mgr ();
1507 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1509 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1510 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1512 /* Menubar. Update the state of some toggles */
1513 priv->from_field_protos = get_transports ();
1514 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1515 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1516 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1517 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1519 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1520 hildon_touch_selector_get_current_text
1521 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1522 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1523 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1526 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1528 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1530 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1531 modest_window_set_active_mailbox (MODEST_WINDOW(obj), mailbox);
1533 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1534 priv->original_mailbox = (mailbox) ? g_strdup (mailbox) : NULL;
1536 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1537 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1538 /* Add common dimming rules */
1539 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1540 modest_msg_edit_window_toolbar_dimming_entries,
1541 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1542 MODEST_WINDOW (obj));
1543 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1544 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1545 MODEST_WINDOW (obj));
1546 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1547 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1548 MODEST_WINDOW (obj));
1549 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1550 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1551 MODEST_WINDOW (obj));
1552 /* Insert dimming rules group for this window */
1553 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1554 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1556 /* Setup app menu */
1557 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1559 /* Checks the dimming rules */
1560 g_object_unref (toolbar_rules_group);
1561 g_object_unref (clipboard_rules_group);
1562 gtk_widget_hide (priv->priority_icon);
1563 gtk_widget_queue_resize (priv->subject_box);
1564 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1566 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1568 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1569 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1570 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1571 priv->update_caption_visibility = TRUE;
1573 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1575 /* Track account-removed signal, this window should be closed
1576 in the case we're creating a mail associated to the account
1578 priv->account_removed_handler_id =
1579 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1581 G_CALLBACK(on_account_removed),
1584 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1586 return (ModestWindow*) obj;
1590 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1592 GString **string_buffer = (GString **) user_data;
1594 *string_buffer = g_string_append (*string_buffer, buffer);
1600 * @result: A new string which should be freed with g_free().
1603 get_formatted_data (ModestMsgEditWindow *edit_window)
1605 ModestMsgEditWindowPrivate *priv;
1606 GString *string_buffer = g_string_new ("");
1608 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1610 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1612 modest_text_utils_hyperlinkify (string_buffer);
1614 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1616 return g_string_free (string_buffer, FALSE);
1621 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1624 const gchar *account_name;
1625 ModestMsgEditWindowPrivate *priv;
1626 TnyIterator *att_iter;
1628 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1630 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1632 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1633 g_return_val_if_fail (account_name, NULL);
1636 /* don't free these (except from) */
1637 data = g_slice_new0 (MsgData);
1638 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1640 data->account_name = g_strdup (account_name);
1641 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1642 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1643 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1644 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1645 data->references = g_strdup (priv->references);
1646 data->in_reply_to = g_strdup (priv->in_reply_to);
1647 if (priv->draft_msg) {
1648 data->draft_msg = g_object_ref (priv->draft_msg);
1649 } else if (priv->outbox_msg) {
1650 data->draft_msg = g_object_ref (priv->outbox_msg);
1652 data->draft_msg = NULL;
1655 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1657 gtk_text_buffer_get_bounds (buf, &b, &e);
1658 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1660 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1661 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1663 data->html_body = NULL;
1665 /* deep-copy the data */
1666 att_iter = tny_list_create_iterator (priv->attachments);
1667 data->attachments = NULL;
1668 while (!tny_iterator_is_done (att_iter)) {
1669 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1670 if (!(TNY_IS_MIME_PART(part))) {
1671 g_warning ("strange data in attachment list");
1672 g_object_unref (part);
1673 tny_iterator_next (att_iter);
1676 data->attachments = g_list_append (data->attachments,
1678 tny_iterator_next (att_iter);
1680 g_object_unref (att_iter);
1682 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1683 att_iter = tny_list_create_iterator (priv->images);
1684 data->images = NULL;
1685 while (!tny_iterator_is_done (att_iter)) {
1686 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1688 if (!(TNY_IS_MIME_PART(part))) {
1689 g_warning ("strange data in attachment list");
1690 g_object_unref (part);
1691 tny_iterator_next (att_iter);
1694 cid = tny_mime_part_get_content_id (part);
1696 gchar *image_tag_id;
1697 GtkTextTag *image_tag;
1699 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1700 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1701 g_free (image_tag_id);
1703 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1705 ((gtk_text_iter_has_tag (&iter, image_tag))||
1706 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1707 data->images = g_list_append (data->images,
1708 g_object_ref (part));
1710 g_object_unref (part);
1711 tny_iterator_next (att_iter);
1713 g_object_unref (att_iter);
1715 data->priority_flags = priv->priority_flags;
1722 unref_gobject (GObject *obj, gpointer data)
1724 if (!G_IS_OBJECT(obj))
1726 g_object_unref (obj);
1730 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1733 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1741 g_free (data->from);
1742 g_free (data->subject);
1743 g_free (data->plain_body);
1744 g_free (data->html_body);
1745 g_free (data->account_name);
1746 g_free (data->references);
1747 g_free (data->in_reply_to);
1749 if (data->draft_msg != NULL) {
1750 g_object_unref (data->draft_msg);
1751 data->draft_msg = NULL;
1754 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1755 g_list_free (data->attachments);
1756 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1757 g_list_free (data->images);
1759 g_slice_free (MsgData, data);
1763 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1765 guint64 *parts_size)
1767 ModestMsgEditWindowPrivate *priv;
1769 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1771 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1773 /* TODO: add images */
1774 *parts_size += priv->images_size;
1775 *parts_count += priv->images_count;
1780 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1783 ModestMsgEditWindowPrivate *priv = NULL;
1784 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1786 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1788 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1790 return MODEST_MSG_EDIT_FORMAT_HTML;
1792 return MODEST_MSG_EDIT_FORMAT_TEXT;
1796 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1797 ModestMsgEditFormat format)
1799 ModestMsgEditWindowPrivate *priv;
1801 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1802 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1805 case MODEST_MSG_EDIT_FORMAT_HTML:
1806 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1808 case MODEST_MSG_EDIT_FORMAT_TEXT:
1809 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1812 g_return_if_reached ();
1816 ModestMsgEditFormatState *
1817 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1819 ModestMsgEditFormatState *format_state = NULL;
1820 ModestMsgEditWindowPrivate *priv;
1821 WPTextBufferFormat *buffer_format;
1823 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1825 buffer_format = g_new0 (WPTextBufferFormat, 1);
1826 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1828 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1830 format_state = g_new0 (ModestMsgEditFormatState, 1);
1831 format_state->bold = buffer_format->bold&0x1;
1832 format_state->italics = buffer_format->italic&0x1;
1833 format_state->bullet = buffer_format->bullet&0x1;
1834 format_state->color = buffer_format->color;
1835 format_state->font_size = buffer_format->font_size;
1836 format_state->font_family = wp_get_font_name (buffer_format->font);
1837 format_state->justification = buffer_format->justification;
1838 g_free (buffer_format);
1840 return format_state;
1845 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1846 const ModestMsgEditFormatState *format_state)
1848 ModestMsgEditWindowPrivate *priv;
1849 WPTextBufferFormat *buffer_format;
1850 WPTextBufferFormat *current_format;
1852 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1853 g_return_if_fail (format_state != NULL);
1855 buffer_format = g_new0 (WPTextBufferFormat, 1);
1856 current_format = g_new0 (WPTextBufferFormat, 1);
1858 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1859 gtk_widget_grab_focus (priv->msg_body);
1860 buffer_format->bold = (format_state->bold != FALSE);
1861 buffer_format->italic = (format_state->italics != FALSE);
1862 buffer_format->color = format_state->color;
1863 buffer_format->font_size = format_state->font_size;
1864 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1865 buffer_format->justification = format_state->justification;
1866 buffer_format->bullet = format_state->bullet;
1868 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1870 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1871 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1872 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1873 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1874 buffer_format->cs.font = (buffer_format->font != current_format->font);
1875 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1876 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1878 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1879 if (buffer_format->cs.bold) {
1880 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1881 GINT_TO_POINTER (buffer_format->bold&0x1));
1883 if (buffer_format->cs.italic) {
1884 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1885 GINT_TO_POINTER (buffer_format->italic&0x1));
1887 if (buffer_format->cs.color) {
1888 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1889 GINT_TO_POINTER (&(buffer_format->color)));
1891 if (buffer_format->cs.font_size) {
1892 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1893 GINT_TO_POINTER (buffer_format->font_size));
1895 if (buffer_format->cs.justification) {
1896 switch (buffer_format->justification) {
1897 case GTK_JUSTIFY_LEFT:
1898 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1899 GINT_TO_POINTER(TRUE));
1901 case GTK_JUSTIFY_CENTER:
1902 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1903 GINT_TO_POINTER(TRUE));
1905 case GTK_JUSTIFY_RIGHT:
1906 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1907 GINT_TO_POINTER(TRUE));
1914 if (buffer_format->cs.font) {
1915 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1916 GINT_TO_POINTER (buffer_format->font));
1918 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1919 if (buffer_format->cs.bullet) {
1920 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1921 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1923 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1925 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1927 g_free (buffer_format);
1928 g_free (current_format);
1930 /* Check dimming rules */
1931 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1932 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1936 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1938 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1940 ModestWindowPrivate *parent_priv;
1941 ModestMsgEditWindowPrivate *priv;
1943 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1944 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1946 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1947 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1948 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1949 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1951 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1952 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1953 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1956 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1958 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1959 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1961 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1962 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1964 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1965 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1968 switch (buffer_format->justification)
1970 case GTK_JUSTIFY_LEFT:
1971 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1973 case GTK_JUSTIFY_CENTER:
1974 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1976 case GTK_JUSTIFY_RIGHT:
1977 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1984 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1986 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1987 G_CALLBACK (modest_msg_edit_window_color_button_change),
1989 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1990 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1991 G_CALLBACK (modest_msg_edit_window_color_button_change),
1994 if (priv->current_size_index != buffer_format->font_size) {
1998 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
1999 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2003 priv->current_size_index = buffer_format->font_size;
2005 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2006 markup = g_strconcat ("<span font_family='Sans'>",
2007 size_text, "</span>", NULL);
2009 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2013 gtk_tree_path_free (path);
2016 if (priv->current_face_index != buffer_format->font) {
2020 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2021 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2025 priv->current_face_index = buffer_format->font;
2026 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2027 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2028 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2035 g_free (buffer_format);
2039 #ifdef MODEST_HILDON_VERSION_0
2041 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2044 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2045 ModestMsgEditWindowPrivate *priv;
2046 GtkWidget *dialog = NULL;
2048 GdkColor *new_color = NULL;
2050 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2051 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2053 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2054 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2055 g_free (buffer_format);
2057 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2058 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2059 if (new_color != NULL) {
2060 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2061 (gpointer) new_color);
2064 gtk_widget_destroy (dialog);
2069 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2072 ModestMsgEditWindowPrivate *priv;
2073 GtkWidget *dialog = NULL;
2075 GdkColor *old_color = NULL;
2076 const GdkColor *new_color = NULL;
2078 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2079 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2081 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2082 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2084 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2085 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2086 if (new_color != NULL)
2087 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2089 gtk_widget_destroy (dialog);
2095 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2098 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2099 ModestMsgEditWindowPrivate *priv;
2100 GtkWidget *dialog = NULL;
2102 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2103 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2105 dialog = hildon_color_chooser_new ();
2106 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2107 g_free (buffer_format);
2109 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2111 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2112 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2115 gtk_widget_destroy (dialog);
2120 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2123 ModestMsgEditWindowPrivate *priv;
2124 GtkWidget *dialog = NULL;
2125 GdkColor *old_color = NULL;
2127 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2128 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2130 dialog = hildon_color_chooser_new ();
2131 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2133 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2135 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2136 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2138 gtk_widget_destroy (dialog);
2141 #endif /*!MODEST_HILDON_VERSION_0*/
2146 create_stream_for_uri (const gchar* uri)
2151 TnyStream *result = NULL;
2153 GnomeVFSHandle *handle = NULL;
2154 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2155 if (test == GNOME_VFS_OK) {
2156 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2157 /* Streams over OBEX (Bluetooth) are not seekable but
2158 * we expect them to be (we might need to read them
2159 * several times). So if this is a Bluetooth URI just
2160 * read the whole file into memory (this is not a fast
2161 * protocol so we can assume that these files are not
2162 * going to be very big) */
2163 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2164 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2165 TnyStream *memstream = tny_camel_mem_stream_new ();
2166 tny_stream_write_to_stream (vfssstream, memstream);
2167 g_object_unref (vfssstream);
2170 result = vfssstream;
2178 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2181 ModestMsgEditWindowPrivate *priv;
2182 GtkWidget *dialog = NULL;
2184 GSList *uris = NULL;
2185 GSList *uri_node = NULL;
2187 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2189 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2190 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2191 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2193 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2195 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2196 GTK_WINDOW (dialog), GTK_WINDOW (window));
2198 response = gtk_dialog_run (GTK_DIALOG (dialog));
2200 case GTK_RESPONSE_OK:
2202 gchar *current_folder;
2203 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2204 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2205 if (current_folder && current_folder != '\0') {
2207 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2208 current_folder, &err);
2210 g_debug ("Error storing latest used folder: %s", err->message);
2214 g_free (current_folder);
2220 gtk_widget_destroy (dialog);
2222 g_object_ref (window);
2223 /* The operation could take some time so allow the dialog to be closed */
2224 while (gtk_events_pending ())
2225 gtk_main_iteration ();
2227 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2229 GnomeVFSHandle *handle = NULL;
2230 GnomeVFSResult result;
2231 GtkTextIter position;
2232 GtkTextMark *insert_mark;
2234 uri = (const gchar *) uri_node->data;
2235 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2236 if (result == GNOME_VFS_OK) {
2238 GnomeVFSFileInfo *info;
2239 gchar *filename, *basename, *escaped_filename;
2240 TnyMimePart *mime_part;
2242 const gchar *mime_type = NULL;
2243 GnomeVFSURI *vfs_uri;
2244 guint64 stream_size;
2246 gnome_vfs_close (handle);
2247 vfs_uri = gnome_vfs_uri_new (uri);
2249 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2250 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2251 g_free (escaped_filename);
2252 gnome_vfs_uri_unref (vfs_uri);
2253 info = gnome_vfs_file_info_new ();
2255 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2256 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2258 mime_type = gnome_vfs_file_info_get_mime_type (info);
2260 mime_part = tny_platform_factory_new_mime_part
2261 (modest_runtime_get_platform_factory ());
2263 TnyStream *stream = create_stream_for_uri (uri);
2265 if (stream == NULL) {
2267 modest_platform_information_banner (NULL, NULL,
2268 _FM("sfil_ib_opening_not_allowed"));
2270 g_object_unref (mime_part);
2271 gnome_vfs_file_info_unref (info);
2275 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2277 content_id = g_strdup_printf ("%d", priv->next_cid);
2278 tny_mime_part_set_content_id (mime_part, content_id);
2279 g_free (content_id);
2282 basename = g_path_get_basename (filename);
2283 tny_mime_part_set_filename (mime_part, basename);
2286 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2288 if (pixbuf != NULL) {
2289 priv->images_size += stream_size;
2290 priv->images_count ++;
2291 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2292 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2293 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2294 tny_mime_part_get_content_id (mime_part), pixbuf);
2295 g_object_unref (pixbuf);
2297 tny_list_prepend (priv->images, (GObject *) mime_part);
2298 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2300 modest_platform_information_banner (NULL, NULL,
2301 _("mail_ib_file_operation_failed"));
2305 g_object_unref (mime_part);
2306 gnome_vfs_file_info_unref (info);
2310 g_object_unref (window);
2314 on_attach_file_response (GtkDialog *dialog,
2318 GSList *uris = NULL;
2320 GnomeVFSFileSize total_size, allowed_size;
2321 ModestMsgEditWindow *window;
2322 ModestMsgEditWindowPrivate *priv;
2327 case GTK_RESPONSE_OK:
2329 gchar *current_folder;
2331 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2332 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2333 if (current_folder && current_folder != '\0') {
2335 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2336 current_folder, &err);
2338 g_debug ("Error storing latest used folder: %s", err->message);
2342 g_free (current_folder);
2349 window = MODEST_MSG_EDIT_WINDOW (user_data);
2350 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2352 /* allowed size is the maximum size - what's already there */
2353 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2354 &att_num, &att_size);
2355 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2358 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2360 const gchar *uri = (const gchar *) uri_node->data;
2363 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2365 if (total_size > allowed_size) {
2366 g_warning ("%s: total size: %u",
2367 __FUNCTION__, (unsigned int)total_size);
2370 allowed_size -= total_size;
2372 g_slist_foreach (uris, (GFunc) g_free, NULL);
2373 g_slist_free (uris);
2375 gtk_widget_destroy (GTK_WIDGET (dialog));
2379 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2381 GtkWidget *dialog = NULL;
2382 ModestMsgEditWindowPrivate *priv;
2385 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2387 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2389 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2392 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2393 GTK_FILE_CHOOSER_ACTION_OPEN);
2394 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2395 conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2396 if (conf_folder && conf_folder[0] != '\0') {
2397 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2400 /* Set the default folder to images folder */
2401 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2402 ".documents", NULL);
2403 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2404 g_free (docs_folder);
2406 g_free (conf_folder);
2407 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2408 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2409 GTK_WINDOW (dialog), GTK_WINDOW (window));
2411 /* Connect to response & show */
2412 g_signal_connect (dialog, "response",
2413 G_CALLBACK (on_attach_file_response), window);
2414 gtk_widget_show (dialog);
2419 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2421 GnomeVFSFileSize allowed_size)
2424 GnomeVFSHandle *handle = NULL;
2425 ModestMsgEditWindowPrivate *priv;
2426 GnomeVFSResult result;
2427 GnomeVFSFileSize size = 0;
2428 g_return_val_if_fail (window, 0);
2429 g_return_val_if_fail (uri, 0);
2431 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2433 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2434 if (result == GNOME_VFS_OK) {
2435 TnyMimePart *mime_part;
2437 const gchar *mime_type = NULL;
2439 gchar *escaped_filename;
2442 GnomeVFSFileInfo *info;
2443 GnomeVFSURI *vfs_uri;
2445 gnome_vfs_close (handle);
2446 vfs_uri = gnome_vfs_uri_new (uri);
2449 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2450 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2451 g_free (escaped_filename);
2452 gnome_vfs_uri_unref (vfs_uri);
2454 info = gnome_vfs_file_info_new ();
2456 if (gnome_vfs_get_file_info (uri,
2458 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2460 mime_type = gnome_vfs_file_info_get_mime_type (info);
2461 mime_part = tny_platform_factory_new_mime_part
2462 (modest_runtime_get_platform_factory ());
2464 /* try to get the attachment's size; this may fail for weird
2465 * file systems, like obex, upnp... */
2466 if (allowed_size != 0 &&
2467 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2469 if (size > allowed_size) {
2470 modest_platform_information_banner (NULL, NULL,
2471 _FM("sfil_ib_opening_not_allowed"));
2476 g_warning ("%s: could not get attachment size", __FUNCTION__);
2478 stream = create_stream_for_uri (uri);
2480 if (stream == NULL) {
2482 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2484 g_object_unref (mime_part);
2486 gnome_vfs_file_info_unref (info);
2490 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2491 g_object_unref (stream);
2493 content_id = g_strdup_printf ("%d", priv->next_cid);
2494 tny_mime_part_set_content_id (mime_part, content_id);
2495 g_free (content_id);
2498 basename = g_path_get_basename (filename);
2499 tny_mime_part_set_filename (mime_part, basename);
2502 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2503 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2505 info->size == 0, info->size);
2506 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2507 gtk_widget_show_all (priv->attachments_caption);
2508 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2510 g_object_unref (mime_part);
2511 gnome_vfs_file_info_unref (info);
2518 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2521 ModestMsgEditWindowPrivate *priv;
2524 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2525 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2527 if (att_list == NULL) {
2528 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2529 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2530 g_object_unref (att_list);
2535 g_object_ref (att_list);
2538 if (tny_list_get_length (att_list) == 0) {
2539 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2541 gboolean dialog_response;
2542 gchar *message = NULL;
2543 gchar *filename = NULL;
2545 if (tny_list_get_length (att_list) == 1) {
2547 iter = tny_list_create_iterator (att_list);
2548 part = (TnyMimePart *) tny_iterator_get_current (iter);
2549 g_object_unref (iter);
2550 if (TNY_IS_MSG (part)) {
2551 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2553 filename = tny_header_dup_subject (header);
2554 g_object_unref (header);
2556 if (filename == NULL) {
2557 filename = g_strdup (_("mail_va_no_subject"));
2560 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2562 g_object_unref (part);
2564 filename = g_strdup ("");
2566 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2567 "emev_nc_delete_attachments",
2568 tny_list_get_length (att_list)), filename);
2571 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2575 if (dialog_response != GTK_RESPONSE_OK) {
2576 g_object_unref (att_list);
2580 for (iter = tny_list_create_iterator (att_list);
2581 !tny_iterator_is_done (iter);
2582 tny_iterator_next (iter)) {
2583 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2584 const gchar *att_id;
2585 tny_list_remove (priv->attachments, (GObject *) mime_part);
2587 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2589 if (tny_list_get_length (priv->attachments) == 0)
2590 gtk_widget_hide (priv->attachments_caption);
2591 att_id = tny_mime_part_get_content_id (mime_part);
2593 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2595 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2596 g_object_unref (mime_part);
2598 g_object_unref (iter);
2601 g_object_unref (att_list);
2603 /* if the last attachment has been removed, focus the Subject: field */
2604 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2605 gtk_widget_grab_focus (priv->subject_field);
2609 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2612 ModestMsgEditWindowPrivate *priv;
2613 GdkColor *new_color;
2614 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2616 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2617 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2620 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2622 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2624 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2626 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2631 font_size_clicked (GtkToolButton *button,
2632 ModestMsgEditWindow *window)
2634 ModestMsgEditWindowPrivate *priv;
2635 GtkWidget *selector, *dialog;
2637 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2639 selector = hildon_touch_selector_new ();
2640 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2641 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2643 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2644 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2645 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2647 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2651 WPTextBufferFormat format;
2653 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2655 memset (&format, 0, sizeof (format));
2656 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2658 format.cs.font_size = TRUE;
2659 format.cs.text_position = TRUE;
2660 format.cs.font = TRUE;
2661 format.font_size = new_index;
2662 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2664 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2665 GINT_TO_POINTER (new_index)))
2666 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2668 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2669 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2670 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2671 size_text, "</span>", NULL);
2673 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2677 gtk_widget_destroy (dialog);
2679 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2684 font_face_clicked (GtkToolButton *button,
2685 ModestMsgEditWindow *window)
2687 ModestMsgEditWindowPrivate *priv;
2688 GtkWidget *selector, *dialog;
2689 GtkCellRenderer *renderer;
2691 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2693 selector = hildon_touch_selector_new ();
2694 renderer = gtk_cell_renderer_text_new ();
2695 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2696 renderer, "family", 0, "text", 0, NULL);
2697 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2699 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2700 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2701 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2703 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2704 gint new_font_index;
2708 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2709 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2710 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2714 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2716 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2717 GINT_TO_POINTER(new_font_index)))
2718 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2720 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2721 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2723 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2727 gtk_tree_path_free (path);
2730 gtk_widget_destroy (dialog);
2732 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2737 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2740 ModestMsgEditWindowPrivate *priv = NULL;
2741 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2743 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2744 if (!priv->update_caption_visibility)
2747 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2749 gtk_widget_show (priv->cc_caption);
2751 gtk_widget_hide (priv->cc_caption);
2753 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2757 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2760 ModestMsgEditWindowPrivate *priv = NULL;
2761 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2763 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2764 if (!priv->update_caption_visibility)
2767 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2769 gtk_widget_show (priv->bcc_caption);
2771 gtk_widget_hide (priv->bcc_caption);
2773 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2777 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2778 ModestRecptEditor *editor)
2780 ModestMsgEditWindowPrivate *priv;
2782 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2783 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2785 /* we check for low-mem; in that case, show a warning, and don't allow
2786 * for the addressbook
2788 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2791 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2793 if (editor == NULL) {
2794 GtkWidget *view_focus;
2795 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2797 /* This code should be kept in sync with ModestRecptEditor. The
2798 textview inside the recpt editor is the one that really gets the
2799 focus. As it's inside a scrolled window, and this one inside the
2800 hbox recpt editor inherits from, we'll need to go up in the
2801 hierarchy to know if the text view is part of the recpt editor
2802 or if it's a different text entry */
2804 if (gtk_widget_get_parent (view_focus)) {
2805 GtkWidget *first_parent;
2807 first_parent = gtk_widget_get_parent (view_focus);
2808 if (gtk_widget_get_parent (first_parent) &&
2809 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2810 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2815 editor = MODEST_RECPT_EDITOR (priv->to_field);
2819 modest_address_book_select_addresses (editor);
2824 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2826 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2828 modest_msg_edit_window_open_addressbook (window, NULL);
2832 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2833 gboolean show_toolbar)
2835 ModestWindowPrivate *parent_priv;
2837 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2838 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2840 /* We can not just use the code of
2841 modest_msg_edit_window_setup_toolbar because it has a
2842 mixture of both initialization and creation code. */
2844 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2846 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2850 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2851 TnyHeaderFlags priority_flags)
2853 ModestMsgEditWindowPrivate *priv;
2854 ModestWindowPrivate *parent_priv;
2856 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2858 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2859 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2861 if (priv->priority_flags != priority_flags) {
2862 GtkAction *priority_action = NULL;
2864 priv->priority_flags = priority_flags;
2866 switch (priority_flags) {
2867 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2868 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2869 MODEST_HEADER_ICON_HIGH,
2870 HILDON_ICON_SIZE_SMALL);
2871 gtk_widget_show (priv->priority_icon);
2872 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2873 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2875 case TNY_HEADER_FLAG_LOW_PRIORITY:
2876 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2877 MODEST_HEADER_ICON_LOW,
2878 HILDON_ICON_SIZE_SMALL);
2879 gtk_widget_show (priv->priority_icon);
2880 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2881 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2884 gtk_widget_hide (priv->priority_icon);
2885 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2886 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2889 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2890 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2892 gtk_widget_queue_resize (priv->subject_box);
2896 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2899 ModestMsgEditWindowPrivate *priv;
2900 ModestWindowPrivate *parent_priv;
2901 gint current_format;
2903 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2905 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2906 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2908 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2909 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2911 if (current_format != file_format) {
2912 switch (file_format) {
2913 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2914 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2915 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2917 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2921 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2922 response = gtk_dialog_run (GTK_DIALOG (dialog));
2923 gtk_widget_destroy (dialog);
2924 if (response == GTK_RESPONSE_OK) {
2925 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2927 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2928 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2933 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2934 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2935 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2940 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2943 ModestMsgEditWindowPrivate *priv;
2944 WPTextBufferFormat oldfmt, fmt;
2945 gint old_position = 0;
2949 GdkColor *color = NULL;
2950 gboolean bold, bold_set, italic, italic_set;
2951 gboolean underline, underline_set;
2952 gboolean strikethrough, strikethrough_set;
2953 gboolean position_set;
2954 gboolean font_size_set, font_set, color_set;
2957 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2958 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2960 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2961 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2962 GTK_WINDOW(dialog), GTK_WINDOW (window));
2964 /* First we get the currently selected font information */
2965 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2967 switch (oldfmt.text_position) {
2968 case TEXT_POSITION_NORMAL:
2971 case TEXT_POSITION_SUPERSCRIPT:
2979 g_object_set (G_OBJECT (dialog),
2980 "bold", oldfmt.bold != FALSE,
2981 "bold-set", !oldfmt.cs.bold,
2982 "underline", oldfmt.underline != FALSE,
2983 "underline-set", !oldfmt.cs.underline,
2984 "italic", oldfmt.italic != FALSE,
2985 "italic-set", !oldfmt.cs.italic,
2986 "strikethrough", oldfmt.strikethrough != FALSE,
2987 "strikethrough-set", !oldfmt.cs.strikethrough,
2988 "color", &oldfmt.color,
2989 "color-set", !oldfmt.cs.color,
2990 "size", wp_font_size[oldfmt.font_size],
2991 "size-set", !oldfmt.cs.font_size,
2992 "position", old_position,
2993 "position-set", !oldfmt.cs.text_position,
2994 "family", wp_get_font_name (oldfmt.font),
2995 "family-set", !oldfmt.cs.font,
2998 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2999 GTK_WINDOW (dialog), GTK_WINDOW (window));
3000 gtk_widget_show_all (dialog);
3001 priv->font_dialog = dialog;
3002 response = gtk_dialog_run (GTK_DIALOG (dialog));
3003 priv->font_dialog = NULL;
3004 if (response == GTK_RESPONSE_OK) {
3006 g_object_get( dialog,
3008 "bold-set", &bold_set,
3009 "underline", &underline,
3010 "underline-set", &underline_set,
3012 "italic-set", &italic_set,
3013 "strikethrough", &strikethrough,
3014 "strikethrough-set", &strikethrough_set,
3016 "color-set", &color_set,
3018 "size-set", &font_size_set,
3019 "family", &font_name,
3020 "family-set", &font_set,
3021 "position", &position,
3022 "position-set", &position_set,
3027 if (response == GTK_RESPONSE_OK) {
3028 memset(&fmt, 0, sizeof(fmt));
3034 fmt.italic = italic;
3035 fmt.cs.italic = TRUE;
3037 if (underline_set) {
3038 fmt.underline = underline;
3039 fmt.cs.underline = TRUE;
3041 if (strikethrough_set) {
3042 fmt.strikethrough = strikethrough;
3043 fmt.cs.strikethrough = TRUE;
3048 ? TEXT_POSITION_NORMAL
3049 : ( ( position == 1 )
3050 ? TEXT_POSITION_SUPERSCRIPT
3051 : TEXT_POSITION_SUBSCRIPT );
3052 fmt.cs.text_position = TRUE;
3053 fmt.font_size = oldfmt.font_size;
3057 fmt.cs.color = TRUE;
3060 fmt.font = wp_get_font_index(font_name,
3065 if (font_size_set) {
3066 fmt.cs.font_size = TRUE;
3067 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3069 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3070 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3072 gtk_widget_destroy (dialog);
3074 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3078 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3080 ModestMsgEditWindowPrivate *priv;
3082 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3083 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3085 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3087 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3088 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3092 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3094 ModestMsgEditWindowPrivate *priv;
3096 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3097 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3099 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3101 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3102 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3107 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3109 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3111 priv->can_undo = can_undo;
3115 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3117 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3119 priv->can_redo = can_redo;
3123 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3125 ModestMsgEditWindowPrivate *priv;
3126 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3127 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3129 return priv->can_undo;
3133 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3135 ModestMsgEditWindowPrivate *priv;
3136 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3137 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3139 return priv->can_redo;
3144 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3147 GtkTextIter match_start, match_end;
3149 if (image_id == NULL)
3152 gtk_text_buffer_get_start_iter (buffer, &iter);
3154 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3155 GSList *tags = gtk_text_iter_get_tags (&match_start);
3157 for (node = tags; node != NULL; node = g_slist_next (node)) {
3158 GtkTextTag *tag = (GtkTextTag *) node->data;
3159 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3160 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3161 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3163 offset = gtk_text_iter_get_offset (&match_start);
3164 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3165 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3169 gtk_text_iter_forward_char (&iter);
3174 message_is_empty (ModestMsgEditWindow *window)
3176 ModestMsgEditWindowPrivate *priv = NULL;
3178 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3179 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3181 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3182 * so we can ignore markup.
3184 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3187 count = gtk_text_buffer_get_char_count (buf);
3193 msg_body_focus (GtkWidget *focus,
3194 GdkEventFocus *event,
3198 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3199 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3200 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3205 recpt_field_changed (GtkTextBuffer *buffer,
3206 ModestMsgEditWindow *editor)
3208 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3209 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3213 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3215 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3216 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3220 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3223 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3224 GtkTextBuffer *buffer;
3226 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3227 gtk_text_buffer_set_modified (buffer, modified);
3228 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3229 gtk_text_buffer_set_modified (buffer, modified);
3230 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3231 gtk_text_buffer_set_modified (buffer, modified);
3232 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3236 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3238 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3239 const char *account_name;
3240 GtkTextBuffer *buffer;
3242 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3243 if (gtk_text_buffer_get_modified (buffer))
3245 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3246 if (gtk_text_buffer_get_modified (buffer))
3248 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3249 if (gtk_text_buffer_get_modified (buffer))
3251 if (gtk_text_buffer_get_modified (priv->text_buffer))
3254 /* TODO: check the mailbox too here */
3255 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3256 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3267 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3269 ModestMsgEditWindowPrivate *priv = NULL;
3271 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3272 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3274 /* check if there's no recipient added */
3275 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3276 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3277 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3278 /* no recipient contents, then select contacts */
3279 modest_msg_edit_window_open_addressbook (window, NULL);
3283 g_object_ref (window);
3284 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3285 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3286 g_object_unref (window);
3289 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3290 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3291 g_object_unref (window);
3294 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3295 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3296 g_object_unref (window);
3300 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3301 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3302 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3303 g_object_unref (window);
3310 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3311 ModestMsgEditWindow *window)
3313 modest_msg_edit_window_offer_attach_file (window);
3317 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3319 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3321 return priv->clipboard_text;
3325 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3327 ModestMsgEditWindow *window)
3329 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3330 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3333 /* It could happen that the window was already closed */
3334 if (!GTK_WIDGET_VISIBLE (window))
3337 g_object_ref (window);
3338 text = gtk_clipboard_wait_for_text (selection_clipboard);
3340 if (priv->clipboard_text != NULL) {
3341 g_free (priv->clipboard_text);
3343 priv->clipboard_text = text;
3345 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3347 g_object_unref (window);
3350 static gboolean clipboard_owner_change_idle (gpointer userdata)
3352 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3353 ModestMsgEditWindowPrivate *priv;
3355 gdk_threads_enter ();
3356 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3357 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3359 priv->clipboard_owner_idle = 0;
3360 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3361 gdk_threads_leave ();
3367 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3369 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3370 if (priv->clipboard_owner_idle == 0) {
3371 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3372 clipboard_owner_change_idle,
3373 g_object_ref (window),
3379 subject_field_move_cursor (GtkEntry *entry,
3380 GtkMovementStep step,
3385 /* It could happen that the window was already closed */
3386 if (!GTK_WIDGET_VISIBLE (window))
3389 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3393 update_window_title (ModestMsgEditWindow *window)
3395 ModestMsgEditWindowPrivate *priv = NULL;
3396 const gchar *subject;
3398 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3399 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3400 if (subject == NULL || subject[0] == '\0')
3401 subject = _("mail_va_new_email");
3403 gtk_window_set_title (GTK_WINDOW (window), subject);
3408 subject_field_changed (GtkEditable *editable,
3409 ModestMsgEditWindow *window)
3411 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3412 update_window_title (window);
3413 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3414 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3415 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3419 subject_field_insert_text (GtkEditable *editable,
3421 gint new_text_length,
3423 ModestMsgEditWindow *window)
3425 GString *result = g_string_new ("");
3427 gint result_len = 0;
3428 const gchar *entry_text = NULL;
3431 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3432 old_length = g_utf8_strlen (entry_text, -1);
3434 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3435 gunichar c = g_utf8_get_char_validated (current, 8);
3436 /* Invalid unichar, stop */
3442 result = g_string_append_unichar (result, c);
3446 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3447 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3450 /* Prevent endless recursion */
3451 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3452 g_signal_emit_by_name (editable, "insert-text",
3453 (gpointer) result->str, (gpointer) result->len,
3454 (gpointer) position, (gpointer) window);
3455 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3459 if (result_len + old_length > 1000) {
3460 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3461 _CS("ckdg_ib_maximum_characters_reached"));
3463 g_string_free (result, TRUE);
3467 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3470 ModestMsgEditWindowPrivate *priv = NULL;
3472 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3473 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3475 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3478 gtk_widget_show_all (priv->find_toolbar);
3479 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3481 gtk_widget_hide_all (priv->find_toolbar);
3482 gtk_widget_grab_focus (priv->msg_body);
3487 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3489 GtkTextIter *match_start,
3490 GtkTextIter *match_end)
3492 GtkTextIter end_iter;
3493 gchar *str_casefold;
3496 gchar *range_casefold;
3499 gboolean result = FALSE;
3506 gtk_text_iter_forward_to_end (&end_iter);
3508 str_casefold = g_utf8_casefold (str, -1);
3509 str_chars_n = strlen (str);
3511 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3512 range_casefold = g_utf8_casefold (range_text, -1);
3513 range_chars_n = strlen (range_casefold);
3515 if (range_chars_n < str_chars_n) {
3516 g_free (str_casefold);
3517 g_free (range_text);
3518 g_free (range_casefold);
3522 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3523 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3524 if (!g_utf8_collate (range_subtext, str_casefold)) {
3525 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3527 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3528 match_start, match_end, NULL)) {
3529 g_warning ("Matched string with collate, but not matched in model");
3531 g_free (found_text);
3533 g_free (range_subtext);
3537 g_free (str_casefold);
3538 g_free (range_text);
3539 g_free (range_casefold);
3546 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3547 ModestMsgEditWindow *window)
3549 gchar *current_search = NULL;
3550 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3552 GtkTextIter selection_start, selection_end;
3553 GtkTextIter match_start, match_end;
3554 gboolean continue_search = FALSE;
3556 if (message_is_empty (window)) {
3557 g_free (priv->last_search);
3558 priv->last_search = NULL;
3559 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3563 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3564 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3565 g_free (current_search);
3566 g_free (priv->last_search);
3567 priv->last_search = NULL;
3568 /* Information banner about empty search */
3569 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3573 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3574 continue_search = TRUE;
3576 g_free (priv->last_search);
3577 priv->last_search = g_strdup (current_search);
3580 if (continue_search) {
3581 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3582 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3583 &match_start, &match_end);
3585 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3587 GtkTextIter buffer_start;
3588 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3589 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3590 &match_start, &match_end);
3592 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3595 /* Mark as selected the string found in search */
3597 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3598 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3599 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3601 g_free (priv->last_search);
3602 priv->last_search = NULL;
3604 g_free (current_search);
3608 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3610 ModestMsgEditWindowPrivate *priv;
3612 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3617 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3620 ModestMsgEditWindowPrivate *priv;
3622 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3627 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3628 ModestMsgEditWindow *window)
3630 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3634 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3637 ModestMsgEditWindowPrivate *priv;
3638 TnyHeader *header = NULL;
3640 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3641 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3643 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3645 if (priv->draft_msg != NULL) {
3646 g_object_unref (priv->draft_msg);
3649 if (draft != NULL) {
3650 g_object_ref (draft);
3651 header = tny_msg_get_header (draft);
3652 if (priv->msg_uid) {
3653 g_free (priv->msg_uid);
3654 priv->msg_uid = NULL;
3656 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3659 priv->draft_msg = draft;
3663 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3664 GtkTextIter *start, GtkTextIter *end,
3667 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3668 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3671 if (tag == NULL) return;
3672 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3673 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3674 replace_with_images (window, priv->images);
3679 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3682 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3684 g_return_if_fail (TNY_IS_MIME_PART (part));
3685 tny_list_prepend (priv->attachments, (GObject *) part);
3686 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3687 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3688 gtk_widget_show_all (priv->attachments_caption);
3689 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3693 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3695 ModestMsgEditWindowPrivate *priv;
3697 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3698 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3700 return priv->msg_uid;
3704 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3705 ModestMsgEditWindowWidgetType widget_type)
3707 ModestMsgEditWindowPrivate *priv;
3709 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3710 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3712 switch (widget_type) {
3713 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3714 return priv->msg_body;
3716 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3717 return priv->to_field;
3719 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3720 return priv->cc_field;
3722 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3723 return priv->bcc_field;
3725 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3726 return priv->subject_field;
3728 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3729 return priv->attachments_view;
3737 remove_tags (WPTextBuffer *buffer)
3739 GtkTextIter start, end;
3741 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3742 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3744 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3748 on_account_removed (TnyAccountStore *account_store,
3749 TnyAccount *account,
3752 /* Do nothing if it's a store account, because we use the
3753 transport to send the messages */
3754 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3755 const gchar *parent_acc = NULL;
3756 const gchar *our_acc = NULL;
3758 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3759 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3760 /* Close this window if I'm showing a message of the removed account */
3761 if (strcmp (parent_acc, our_acc) == 0)
3762 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3767 from_field_changed (HildonPickerButton *button,
3768 ModestMsgEditWindow *self)
3770 ModestMsgEditWindowPrivate *priv;
3771 gboolean has_old_signature, has_new_signature;
3773 GtkTextIter match_start, match_end;
3774 ModestAccountMgr *mgr;
3776 gchar *full_signature;
3778 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3780 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3781 mgr = modest_runtime_get_account_mgr ();
3782 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3783 if (has_old_signature) {
3784 full_signature = g_strconcat ("\n--\n", signature, NULL);
3785 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3786 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3788 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3789 &match_start, &match_end, NULL)) {
3792 g_free (full_signature);
3796 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3797 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3798 if (has_new_signature) {
3799 full_signature = g_strconcat ("\n--\n", signature, NULL);
3800 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3801 g_free (full_signature);
3806 typedef struct _MessageSettingsHelper {
3807 ModestMsgEditWindow *window;
3808 GSList *priority_group;
3809 GSList *format_group;
3810 GtkToggleButton *current_priority;
3811 GtkToggleButton *current_format;
3812 } MessageSettingsHelper;
3815 on_priority_toggle (GtkToggleButton *button,
3816 MessageSettingsHelper *helper)
3819 ModestMsgEditWindowPrivate *priv;
3821 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3822 if (gtk_toggle_button_get_active (button)) {
3824 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3825 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3826 if ((node_button != button) &&
3827 gtk_toggle_button_get_active (node_button)) {
3828 gtk_toggle_button_set_active (node_button, FALSE);
3831 helper->current_priority = button;
3833 gboolean found = FALSE;
3834 /* If no one is active, activate it again */
3835 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3836 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3837 if (gtk_toggle_button_get_active (node_button)) {
3843 gtk_toggle_button_set_active (button, TRUE);
3849 on_format_toggle (GtkToggleButton *button,
3850 MessageSettingsHelper *helper)
3853 ModestMsgEditWindowPrivate *priv;
3855 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3856 if (gtk_toggle_button_get_active (button)) {
3858 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3859 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3860 if ((node_button != button) &&
3861 gtk_toggle_button_get_active (node_button)) {
3862 gtk_toggle_button_set_active (node_button, FALSE);
3865 helper->current_format = button;
3867 gboolean found = FALSE;
3868 /* If no one is active, activate it again */
3869 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3870 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3871 if (gtk_toggle_button_get_active (node_button)) {
3877 gtk_toggle_button_set_active (button, TRUE);
3884 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3889 GtkWidget *priority_hbox;
3890 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3891 GtkWidget *captioned;
3892 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3893 GtkWidget *format_hbox;
3894 GtkWidget *html_toggle, *text_toggle;
3895 ModestMsgEditWindowPrivate *priv;
3896 MessageSettingsHelper helper = {0,};
3898 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3899 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3900 helper.window = window;
3901 helper.priority_group = NULL;
3902 helper.format_group = NULL;
3904 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3905 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3907 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3908 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3909 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3910 vbox = gtk_vbox_new (FALSE, 0);
3911 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
3912 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
3913 gtk_container_add (GTK_CONTAINER (align), vbox);
3914 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
3915 gtk_widget_show (align);
3916 gtk_widget_show (vbox);
3918 /* Priority toggles */
3919 priority_hbox = gtk_hbox_new (TRUE, 0);
3920 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3921 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3922 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3923 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3924 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3925 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3926 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3927 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3928 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3929 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3930 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3931 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3932 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3933 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3934 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3935 gtk_widget_show_all (priority_hbox);
3936 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3937 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3938 gtk_widget_show (captioned);
3939 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3941 /* format toggles */
3942 format_hbox = gtk_hbox_new (TRUE, 0);
3943 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3944 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3945 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3946 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3947 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3948 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3949 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3950 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3951 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3952 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3953 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3954 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3955 gtk_widget_show_all (format_hbox);
3956 gtk_widget_show (format_hbox);
3957 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3960 g_object_unref (title_sizegroup);
3961 g_object_unref (value_sizegroup);
3963 /* Set current values */
3964 switch (priv->priority_flags) {
3965 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3966 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3967 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3969 case TNY_HEADER_FLAG_LOW_PRIORITY:
3970 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3971 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3974 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3975 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3979 switch (modest_msg_edit_window_get_format (window)) {
3980 case MODEST_MSG_EDIT_FORMAT_TEXT:
3981 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3982 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3984 case MODEST_MSG_EDIT_FORMAT_HTML:
3986 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3987 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3991 /* Signal connects */
3992 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3993 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3994 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3995 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3996 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3998 /* Save settings if the user clicked on done */
3999 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4000 TnyHeaderFlags flags;
4001 ModestMsgEditFormat old_format, new_format;
4003 /* Set priority flags */
4004 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4005 if (priv->priority_flags != flags)
4006 modest_msg_edit_window_set_priority_flags (window, flags);
4008 /* Set edit format */
4009 old_format = modest_msg_edit_window_get_format (window);
4010 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4011 if (old_format != new_format) {
4012 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4013 modest_msg_edit_window_set_file_format (window, file_format);
4017 gtk_widget_destroy (dialog);
4018 g_slist_free (helper.priority_group);
4022 on_message_settings (GtkAction *action,
4023 ModestMsgEditWindow *window)
4025 modest_msg_edit_window_show_msg_settings_dialog (window);
4029 on_cc_button_toggled (HildonCheckButton *button,
4030 ModestMsgEditWindow *window)
4032 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4034 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4035 hildon_check_button_get_active (button));
4039 on_bcc_button_toggled (HildonCheckButton *button,
4040 ModestMsgEditWindow *window)
4042 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4044 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4045 hildon_check_button_get_active (button));
4049 setup_menu (ModestMsgEditWindow *self)
4051 ModestMsgEditWindowPrivate *priv = NULL;
4053 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4055 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4057 /* Settings menu buttons */
4058 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4059 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4061 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4062 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4063 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4065 priv->cc_button = hildon_check_button_new (0);
4066 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4067 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4069 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4071 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4072 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4073 priv->bcc_button = hildon_check_button_new (0);
4074 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4075 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4077 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4079 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4080 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4082 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4083 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4084 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4085 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4086 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4087 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4088 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4089 APP_MENU_CALLBACK (on_message_settings),
4091 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4092 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),