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;
247 GtkWidget *bcc_field;
248 GtkWidget *subject_field;
249 GtkWidget *attachments_view;
250 GtkWidget *priority_icon;
251 GtkWidget *subject_box;
252 GtkWidget *add_attachment_button;
254 GtkWidget *cc_caption;
255 GtkWidget *bcc_caption;
256 gboolean update_caption_visibility;
257 GtkWidget *attachments_caption;
259 GtkTextBuffer *text_buffer;
261 GtkWidget *font_size_toolitem;
262 GtkWidget *font_face_toolitem;
263 GtkWidget *font_color_button;
264 GtkWidget *font_color_toolitem;
265 GSList *font_items_group;
266 GtkTreeModel *faces_model;
267 gint current_face_index;
268 GtkWidget *font_tool_button_label;
269 GtkTreeModel *sizes_model;
270 gint current_size_index;
271 GtkWidget *size_tool_button_label;
273 GtkWidget *find_toolbar;
276 GtkWidget *font_dialog;
279 guint correct_scroll_idle;
280 guint scroll_drag_timeout_id;
284 TnyList *attachments;
289 TnyHeaderFlags priority_flags;
291 gboolean can_undo, can_redo;
292 gulong clipboard_change_handler_id;
293 gulong default_clipboard_change_handler_id;
294 gulong account_removed_handler_id;
295 guint clipboard_owner_idle;
296 gchar *clipboard_text;
305 GtkWidget *cc_button;
306 GtkWidget *bcc_button;
309 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
310 MODEST_TYPE_MSG_EDIT_WINDOW, \
311 ModestMsgEditWindowPrivate))
313 static GtkWindowClass *parent_class = NULL;
315 /* uncomment the following if you have defined any signals */
316 /* static guint signals[LAST_SIGNAL] = {0}; */
319 modest_msg_edit_window_get_type (void)
321 static GType my_type = 0;
323 static const GTypeInfo my_info = {
324 sizeof(ModestMsgEditWindowClass),
325 NULL, /* base init */
326 NULL, /* base finalize */
327 (GClassInitFunc) modest_msg_edit_window_class_init,
328 NULL, /* class finalize */
329 NULL, /* class data */
330 sizeof(ModestMsgEditWindow),
332 (GInstanceInitFunc) modest_msg_edit_window_init,
335 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
336 "ModestMsgEditWindow",
344 save_state (ModestWindow *self)
346 modest_widget_memory_save (modest_runtime_get_conf(),
347 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
352 restore_settings (ModestMsgEditWindow *self)
354 ModestConf *conf = NULL;
356 conf = modest_runtime_get_conf ();
358 /* Dim at start clipboard actions */
359 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
364 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
366 GObjectClass *gobject_class;
367 ModestWindowClass *modest_window_class;
368 gobject_class = (GObjectClass*) klass;
369 modest_window_class = (ModestWindowClass*) klass;
371 parent_class = g_type_class_peek_parent (klass);
372 gobject_class->finalize = modest_msg_edit_window_finalize;
374 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
375 modest_window_class->save_state_func = save_state;
376 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
378 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
382 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
384 ModestMsgEditWindowPrivate *priv;
385 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
387 priv->msg_body = NULL;
388 priv->from_field = NULL;
389 priv->to_field = NULL;
390 priv->cc_field = NULL;
391 priv->bcc_field = NULL;
392 priv->subject_field = NULL;
393 priv->attachments = TNY_LIST (tny_simple_list_new ());
394 priv->images = TNY_LIST (tny_simple_list_new ());
395 priv->images_size = 0;
396 priv->images_count = 0;
399 priv->cc_caption = NULL;
400 priv->bcc_caption = NULL;
401 priv->update_caption_visibility = FALSE;
403 priv->priority_flags = 0;
405 priv->find_toolbar = NULL;
406 priv->last_search = NULL;
408 priv->draft_msg = NULL;
409 priv->outbox_msg = NULL;
410 priv->msg_uid = NULL;
412 priv->can_undo = FALSE;
413 priv->can_redo = FALSE;
414 priv->clipboard_change_handler_id = 0;
415 priv->default_clipboard_change_handler_id = 0;
416 priv->account_removed_handler_id = 0;
417 priv->clipboard_owner_idle = 0;
418 priv->clipboard_text = NULL;
421 priv->scroll_drag_timeout_id = 0;
422 priv->correct_scroll_idle = 0;
423 priv->last_upper = 0.0;
425 priv->font_dialog = NULL;
426 priv->app_menu = NULL;
428 if (!is_wp_text_buffer_started) {
429 is_wp_text_buffer_started = TRUE;
430 wp_text_buffer_library_init ();
435 hildon_program_add_window (hildon_program_get_instance(),
441 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
443 static ModestPairList*
444 get_transports (void)
446 GSList *transports = NULL;
448 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
449 GSList *accounts = modest_account_mgr_account_names (account_mgr,
450 TRUE /* only enabled accounts. */);
452 GSList *cursor = accounts;
454 gchar *account_name = cursor->data;
455 gchar *from_string = NULL;
457 from_string = modest_account_mgr_get_from_string (account_mgr,
461 if (from_string && account_name) {
462 gchar *name = account_name;
463 ModestPair *pair = modest_pair_new ((gpointer) name,
464 (gpointer) from_string , TRUE);
465 transports = g_slist_prepend (transports, pair);
468 cursor = cursor->next;
470 g_slist_free (accounts); /* only free the accounts, not the elements,
471 * because they are used in the pairlist */
475 static void window_focus (GtkWindow *window,
479 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
483 scroll_drag_timeout (gpointer userdata)
485 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
486 ModestMsgEditWindowPrivate *priv;
488 /* It could happen that the window was already closed */
489 if (!GTK_WIDGET_VISIBLE (win))
492 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
494 correct_scroll_without_drag_check (win, TRUE);
496 priv->scroll_drag_timeout_id = 0;
502 correct_scroll_without_drag_check_idle (gpointer userdata)
504 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
505 ModestMsgEditWindowPrivate *priv;
507 GdkRectangle rectangle;
508 gint offset_min, offset_max;
512 /* It could happen that the window was already closed */
513 if (!GTK_WIDGET_VISIBLE (w))
516 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
518 insert = gtk_text_buffer_get_insert (priv->text_buffer);
519 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
521 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
522 offset_min = priv->msg_body->allocation.y + rectangle.y;
523 offset_max = offset_min + rectangle.height;
525 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
526 offset_min = MAX (offset_min - 48, 0);
527 offset_max = MIN (offset_max + 48, vadj->upper);
529 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
531 priv->correct_scroll_idle = 0;
536 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
538 ModestMsgEditWindowPrivate *priv;
540 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
542 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
545 if (priv->correct_scroll_idle > 0) {
549 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
550 (GSourceFunc) correct_scroll_without_drag_check_idle,
556 correct_scroll (ModestMsgEditWindow *w)
558 ModestMsgEditWindowPrivate *priv;
560 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
561 if (gtk_grab_get_current () == priv->msg_body) {
562 if (priv->scroll_drag_timeout_id == 0) {
563 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
565 (GSourceFunc) scroll_drag_timeout,
572 correct_scroll_without_drag_check (w, TRUE);
576 text_buffer_end_user_action (GtkTextBuffer *buffer,
577 ModestMsgEditWindow *userdata)
580 correct_scroll (userdata);
584 text_buffer_mark_set (GtkTextBuffer *buffer,
587 ModestMsgEditWindow *userdata)
589 gtk_text_buffer_begin_user_action (buffer);
590 gtk_text_buffer_end_user_action (buffer);
594 cut_clipboard_check (GtkTextView *text_view,
597 GtkTextBuffer *buffer;
599 buffer = gtk_text_view_get_buffer (text_view);
600 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
601 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
606 copy_clipboard_check (GtkTextView *text_view,
609 GtkTextBuffer *buffer;
611 buffer = gtk_text_view_get_buffer (text_view);
612 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
613 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
618 attachment_deleted (ModestAttachmentsView *attachments_view,
621 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
626 connect_signals (ModestMsgEditWindow *obj)
628 ModestMsgEditWindowPrivate *priv;
630 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
632 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
633 G_CALLBACK (text_buffer_refresh_attributes), obj);
634 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
635 G_CALLBACK (text_buffer_can_undo), obj);
636 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
637 G_CALLBACK (text_buffer_can_redo), obj);
638 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
639 G_CALLBACK (body_changed), obj);
640 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
641 G_CALLBACK (body_changed), obj);
642 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
643 G_CALLBACK (text_buffer_end_user_action), obj);
644 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
645 G_CALLBACK (text_buffer_mark_set), obj);
646 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
647 G_CALLBACK (text_buffer_apply_tag), obj);
648 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
649 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
650 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
651 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
652 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
653 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
655 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
656 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
657 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
658 G_CALLBACK (from_field_changed), obj);
660 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
661 G_CALLBACK (msg_body_focus), obj);
662 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
663 G_CALLBACK (msg_body_focus), obj);
664 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
665 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
666 "changed", G_CALLBACK (recpt_field_changed), obj);
667 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
668 "changed", G_CALLBACK (recpt_field_changed), obj);
669 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
670 "changed", G_CALLBACK (recpt_field_changed), obj);
671 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
672 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
673 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
675 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
676 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
678 priv->clipboard_change_handler_id =
679 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
680 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
681 priv->default_clipboard_change_handler_id =
682 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
683 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
685 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
686 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
687 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
691 init_wp_text_view_style ()
693 static gboolean initialized = FALSE;
696 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
702 init_window (ModestMsgEditWindow *obj)
704 GtkWidget *to_caption, *subject_caption;
705 GtkWidget *main_vbox;
706 GtkWidget *add_attachment_align;
707 ModestMsgEditWindowPrivate *priv;
708 GtkActionGroup *action_group;
709 ModestWindowPrivate *parent_priv;
710 GdkPixbuf *window_icon = NULL;
711 GError *error = NULL;
713 GtkSizeGroup *title_size_group;
714 GtkSizeGroup *value_size_group;
715 GtkWidget *attachment_icon;
716 GtkWidget *window_box;
717 GtkWidget *window_align;
718 #if (GTK_MINOR_VERSION >= 10)
719 GdkAtom deserialize_type;
722 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
723 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
725 parent_priv->ui_manager = gtk_ui_manager_new();
726 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
727 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
729 /* Add common actions */
730 gtk_action_group_add_actions (action_group,
731 modest_msg_edit_action_entries,
732 G_N_ELEMENTS (modest_msg_edit_action_entries),
734 gtk_action_group_add_actions (action_group,
735 hildon2_msg_edit_action_entries,
736 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
738 gtk_action_group_add_toggle_actions (action_group,
739 modest_msg_edit_toggle_action_entries,
740 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
742 gtk_action_group_add_radio_actions (action_group,
743 modest_msg_edit_alignment_radio_action_entries,
744 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
746 G_CALLBACK (modest_ui_actions_on_change_justify),
748 gtk_action_group_add_radio_actions (action_group,
749 modest_msg_edit_priority_action_entries,
750 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
752 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
754 gtk_action_group_add_radio_actions (action_group,
755 modest_msg_edit_file_format_action_entries,
756 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
757 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
758 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
760 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
761 g_object_unref (action_group);
763 /* Load the UI definition */
764 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
767 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
768 g_clear_error (&error);
771 /* Add accelerators */
772 gtk_window_add_accel_group (GTK_WINDOW (obj),
773 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
775 parent_priv->menubar = NULL;
777 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
778 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
780 /* Note: This ModestPairList* must exist for as long as the picker
781 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
782 * so it can't know how to manage its memory. */
783 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
784 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
786 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
787 _("mail_va_from"), priv->from_field);
789 priv->to_field = modest_recpt_editor_new ();
790 priv->cc_field = modest_recpt_editor_new ();
791 priv->bcc_field = modest_recpt_editor_new ();
792 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
793 priv->priority_icon = gtk_image_new ();
794 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
795 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
796 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
797 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
798 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
799 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
800 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
801 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
802 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
803 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
804 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
805 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
806 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
807 add_attachment_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
808 gtk_alignment_set_padding (GTK_ALIGNMENT (add_attachment_align), 0, 0, MODEST_MARGIN_DEFAULT, 0);
809 gtk_container_add (GTK_CONTAINER (add_attachment_align), priv->add_attachment_button);
810 gtk_box_pack_start (GTK_BOX (priv->subject_box), add_attachment_align, FALSE, FALSE, 0);
811 priv->attachments_view = modest_attachments_view_new (NULL);
812 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
813 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
815 priv->header_box = gtk_vbox_new (FALSE, 0);
817 to_caption = modest_maemo_utils_create_captioned_with_size_type
818 (title_size_group, value_size_group,
819 _("mail_va_to"), FALSE, priv->to_field,
820 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
821 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
822 (title_size_group, value_size_group,
823 _("mail_va_cc"), FALSE, priv->cc_field,
824 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
825 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
826 (title_size_group, value_size_group,
827 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
828 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
829 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
830 _("mail_va_subject"), FALSE, priv->subject_box);
831 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
832 _("mail_va_attachment"),
834 priv->attachments_view,
835 HILDON_SIZE_AUTO_WIDTH |
836 HILDON_SIZE_AUTO_HEIGHT);
837 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
838 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
839 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
840 g_object_unref (title_size_group);
841 g_object_unref (value_size_group);
843 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
844 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
845 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
846 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
847 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
848 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
849 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
851 init_wp_text_view_style ();
853 priv->msg_body = modest_wp_text_view_new ();
856 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
857 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
858 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
859 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
860 #if (GTK_MINOR_VERSION >= 10)
861 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
862 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
864 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
865 deserialize_type, TRUE);
867 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
869 priv->find_toolbar = hildon_find_toolbar_new (NULL);
870 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
872 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
874 priv->pannable = hildon_pannable_area_new ();
876 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
877 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
878 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
880 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
881 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
882 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
884 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
885 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox),
886 hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable)));
887 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
889 window_box = gtk_vbox_new (FALSE, 0);
890 gtk_container_add (GTK_CONTAINER(obj), window_box);
892 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
894 /* Set window icon */
895 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
897 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
898 g_object_unref (window_icon);
903 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
905 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
907 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
908 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
909 priv->clipboard_change_handler_id))
910 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
911 priv->clipboard_change_handler_id);
912 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
913 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
914 priv->default_clipboard_change_handler_id))
915 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
916 priv->default_clipboard_change_handler_id);
918 if (priv->account_removed_handler_id &&
919 g_signal_handler_is_connected (modest_runtime_get_account_store (),
920 priv->account_removed_handler_id))
921 g_signal_handler_disconnect(modest_runtime_get_account_store (),
922 priv->account_removed_handler_id);
926 modest_msg_edit_window_finalize (GObject *obj)
928 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
930 /* Sanity check: shouldn't be needed, the window mgr should
931 call this function before */
932 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
934 if (priv->font_dialog != NULL) {
935 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
938 if (priv->clipboard_text != NULL) {
939 g_free (priv->clipboard_text);
940 priv->clipboard_text = NULL;
943 if (priv->draft_msg != NULL) {
944 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
945 if (TNY_IS_HEADER (header)) {
946 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
947 modest_window_mgr_unregister_header (mgr, header);
949 g_object_unref (priv->draft_msg);
950 priv->draft_msg = NULL;
952 if (priv->outbox_msg != NULL) {
953 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
954 if (TNY_IS_HEADER (header)) {
955 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
956 modest_window_mgr_unregister_header (mgr, header);
958 g_object_unref (priv->outbox_msg);
959 priv->outbox_msg = NULL;
961 if (priv->correct_scroll_idle > 0) {
962 g_source_remove (priv->correct_scroll_idle);
963 priv->correct_scroll_idle = 0;
965 if (priv->scroll_drag_timeout_id > 0) {
966 g_source_remove (priv->scroll_drag_timeout_id);
967 priv->scroll_drag_timeout_id = 0;
969 if (priv->clipboard_owner_idle > 0) {
970 g_source_remove (priv->clipboard_owner_idle);
971 priv->clipboard_owner_idle = 0;
973 if (priv->original_account_name)
974 g_free (priv->original_account_name);
975 g_free (priv->msg_uid);
976 g_free (priv->last_search);
977 g_object_unref (priv->faces_model);
978 g_object_unref (priv->sizes_model);
979 g_object_unref (priv->attachments);
980 g_object_unref (priv->images);
982 /* This had to stay alive for as long as the picker that used it: */
983 modest_pair_list_free (priv->from_field_protos);
985 G_OBJECT_CLASS(parent_class)->finalize (obj);
989 pixbuf_size_prepared (GdkPixbufLoader *loader,
992 ModestMsgEditWindow *self)
994 gint new_height, new_width;
1001 if (width > IMAGE_MAX_WIDTH) {
1002 new_height = height * IMAGE_MAX_WIDTH / width;
1003 new_width = IMAGE_MAX_WIDTH;
1006 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1010 pixbuf_from_stream (TnyStream *stream,
1011 const gchar *mime_type,
1012 guint64 *stream_size,
1013 ModestMsgEditWindow *self)
1015 GdkPixbufLoader *loader;
1018 GError *error = NULL;
1022 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1024 if (loader == NULL) {
1029 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1031 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1033 tny_stream_reset (TNY_STREAM (stream));
1034 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1035 unsigned char read_buffer[128];
1037 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1039 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1042 /* Allow some UI responsiveness */
1043 while (gtk_events_pending ())
1044 gtk_main_iteration ();
1046 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1048 gdk_pixbuf_loader_close (loader, &error);
1051 g_error_free (error);
1052 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1054 g_object_ref (pixbuf);
1055 g_object_unref (loader);
1060 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1061 GdkPixbuf *new_pixbuf;
1063 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1064 gdk_pixbuf_get_width (pixbuf);
1065 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1066 g_object_unref (pixbuf);
1067 pixbuf = new_pixbuf;
1071 *stream_size = size;
1077 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1079 ModestMsgEditWindowPrivate *priv;
1082 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1084 g_object_ref (self);
1085 for (iter = tny_list_create_iterator (attachments);
1086 !tny_iterator_is_done (iter);
1087 tny_iterator_next (iter)) {
1088 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1089 const gchar *cid = tny_mime_part_get_content_id (part);
1090 const gchar *mime_type = tny_mime_part_get_content_type (part);
1091 if ((cid != NULL)&&(mime_type != NULL)) {
1092 guint64 stream_size;
1093 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1094 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1097 g_object_unref (stream);
1099 if (pixbuf != NULL) {
1100 priv->images_count ++;
1101 priv->images_size += stream_size;
1102 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1103 g_object_unref (pixbuf);
1106 g_object_unref (part);
1108 g_object_unref (iter);
1109 g_object_unref (self);
1113 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1115 TnyMimePart *parent = NULL;
1116 const gchar *content_type = NULL;
1117 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1119 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1121 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1122 parent = g_object_ref (msg);
1123 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1124 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1127 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1128 iter = tny_list_create_iterator (parts);
1129 while (!tny_iterator_is_done (iter)) {
1131 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1132 content_type = tny_mime_part_get_content_type (part);
1133 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1137 g_object_unref (part);
1139 tny_iterator_next (iter);
1141 g_object_unref (iter);
1142 g_object_unref (parts);
1145 if (parent != NULL) {
1146 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1149 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1150 iter = tny_list_create_iterator (parts);
1151 while (!tny_iterator_is_done (iter)) {
1153 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1154 content_type = tny_mime_part_get_content_type (part);
1155 if (content_type && g_str_has_prefix (content_type, "image/")) {
1156 tny_list_prepend (priv->images, (GObject *) part);
1158 g_object_unref (part);
1159 tny_iterator_next (iter);
1161 g_object_unref (iter);
1162 g_object_unref (parts);
1163 g_object_unref (parent);
1168 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1171 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1173 for (iter = tny_list_create_iterator (attachments) ;
1174 !tny_iterator_is_done (iter);
1175 tny_iterator_next (iter)) {
1176 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1177 const gchar *cid = tny_mime_part_get_content_id (part);
1179 char *invalid = NULL;
1180 gint int_cid = strtol (cid, &invalid, 10);
1181 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1182 priv->next_cid = int_cid + 1;
1185 g_object_unref (part);
1187 g_object_unref (iter);
1191 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1194 gchar *to, *cc, *bcc, *subject;
1196 ModestMsgEditWindowPrivate *priv;
1197 ModestWindowPrivate *parent_priv;
1199 TnyHeaderFlags priority_flags;
1200 TnyFolder *msg_folder;
1201 gboolean is_html = FALSE;
1202 gboolean field_view_set;
1204 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1205 g_return_if_fail (TNY_IS_MSG (msg));
1207 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1208 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1210 header = tny_msg_get_header (msg);
1211 to = tny_header_dup_to (header);
1212 cc = tny_header_dup_cc (header);
1213 bcc = tny_header_dup_bcc (header);
1214 subject = tny_header_dup_subject (header);
1215 priority_flags = tny_header_get_priority (header);
1218 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1220 field_view_set = TRUE;
1222 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1223 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1224 gtk_widget_show (priv->cc_caption);
1225 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1226 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1227 gtk_widget_hide (priv->cc_caption);
1228 field_view_set = FALSE;
1230 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1232 field_view_set = TRUE;
1234 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1235 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1236 gtk_widget_show (priv->bcc_caption);
1237 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1238 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1239 gtk_widget_hide (priv->bcc_caption);
1240 field_view_set = FALSE;
1242 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1246 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1247 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1250 update_window_title (self);
1252 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1253 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1255 if ((body == NULL)||(body[0] == '\0')) {
1257 body = modest_text_utils_convert_to_html ("");
1260 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1261 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1264 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1267 /* Add attachments to the view */
1268 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1269 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1270 if (tny_list_get_length (priv->attachments) == 0) {
1271 gtk_widget_hide (priv->attachments_caption);
1273 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1274 gtk_widget_show_all (priv->attachments_caption);
1276 get_related_images (self, msg);
1277 update_next_cid (self, priv->attachments);
1278 update_next_cid (self, priv->images);
1279 replace_with_images (self, priv->images);
1281 if (preserve_is_rich && !is_html) {
1282 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1283 /* Get the default format required from configuration */
1284 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1285 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1288 /* Set the default focus depending on having already a To: field or not */
1289 if ((!to)||(*to == '\0')) {
1290 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1292 gtk_widget_grab_focus (priv->msg_body);
1295 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1297 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1298 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1300 modest_msg_edit_window_set_modified (self, FALSE);
1302 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1303 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1304 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1305 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1307 if (priv->msg_uid) {
1308 g_free (priv->msg_uid);
1309 priv->msg_uid = NULL;
1312 /* we should set a reference to the incoming message if it is a draft */
1313 msg_folder = tny_msg_get_folder (msg);
1315 if (modest_tny_folder_is_local_folder (msg_folder)) {
1316 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1317 if (type == TNY_FOLDER_TYPE_INVALID)
1318 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1320 if (type == TNY_FOLDER_TYPE_DRAFTS)
1321 priv->draft_msg = g_object_ref(msg);
1322 if (type == TNY_FOLDER_TYPE_OUTBOX)
1323 priv->outbox_msg = g_object_ref(msg);
1324 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1326 g_object_unref (msg_folder);
1337 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1339 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1340 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1341 GtkWidget *placeholder;
1342 GtkWidget *tool_item;
1347 GtkWidget *sizes_menu;
1348 GtkWidget *fonts_menu;
1352 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1353 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1354 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1355 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1357 /* Font color placeholder */
1358 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1359 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1362 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1363 priv->font_color_button = hildon_color_button_new ();
1364 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1365 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1366 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1367 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1368 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1369 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1370 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1371 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1373 G_CALLBACK (modest_msg_edit_window_color_button_change),
1376 /* Font size and face placeholder */
1377 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1378 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1380 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1381 priv->size_tool_button_label = gtk_label_new (NULL);
1382 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1383 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1384 size_text, "</span>", NULL);
1385 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1387 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1388 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1389 sizes_menu = gtk_menu_new ();
1390 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1391 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1394 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1395 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1397 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1401 if (wp_font_size[size_index] == 12)
1402 priv->current_size_index = size_index;
1406 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1407 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1408 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1409 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1410 priv->font_size_toolitem = tool_item;
1413 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1414 priv->font_tool_button_label = gtk_label_new (NULL);
1415 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1416 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1418 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1419 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1420 fonts_menu = gtk_menu_new ();
1421 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1422 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1425 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1427 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1428 0, wp_get_font_name (font_index),
1431 if (font_index == DEFAULT_FONT)
1432 priv->current_face_index = font_index;
1434 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1435 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1436 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1437 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1438 priv->font_face_toolitem = tool_item;
1440 /* Set expand and homogeneous for remaining items */
1441 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1442 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1443 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1444 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1445 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1446 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1447 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1448 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1449 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1451 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1452 will not show the tool items added to the placeholders) */
1453 gtk_widget_show_all (parent_priv->toolbar);
1455 /* Set the no show all *after* showing all items. We do not
1456 want the toolbar to be shown with a show all because it
1457 could go agains the gconf setting regarding showing or not
1458 the toolbar of the editor window */
1459 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1465 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1468 ModestWindowPrivate *parent_priv;
1469 ModestMsgEditWindowPrivate *priv;
1470 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1471 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1472 ModestWindowMgr *mgr = NULL;
1474 g_return_val_if_fail (msg, NULL);
1475 g_return_val_if_fail (account_name, NULL);
1477 mgr = modest_runtime_get_window_mgr ();
1479 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1481 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1482 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1484 /* Menubar. Update the state of some toggles */
1485 priv->from_field_protos = get_transports ();
1486 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1487 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1488 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1489 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1491 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1492 hildon_touch_selector_get_current_text
1493 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1494 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1495 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1498 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1500 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1502 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1504 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1506 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1507 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1508 /* Add common dimming rules */
1509 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1510 modest_msg_edit_window_toolbar_dimming_entries,
1511 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1512 MODEST_WINDOW (obj));
1513 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1514 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1515 MODEST_WINDOW (obj));
1516 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1517 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1518 MODEST_WINDOW (obj));
1519 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1520 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1521 MODEST_WINDOW (obj));
1522 /* Insert dimming rules group for this window */
1523 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1524 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1526 /* Setup app menu */
1527 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1529 /* Checks the dimming rules */
1530 g_object_unref (toolbar_rules_group);
1531 g_object_unref (clipboard_rules_group);
1532 gtk_widget_hide (priv->priority_icon);
1533 gtk_widget_queue_resize (priv->subject_box);
1534 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1536 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1538 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1539 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1540 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1541 priv->update_caption_visibility = TRUE;
1543 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1545 /* Track account-removed signal, this window should be closed
1546 in the case we're creating a mail associated to the account
1548 priv->account_removed_handler_id =
1549 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1551 G_CALLBACK(on_account_removed),
1554 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1556 return (ModestWindow*) obj;
1560 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1562 GString **string_buffer = (GString **) user_data;
1564 *string_buffer = g_string_append (*string_buffer, buffer);
1570 * @result: A new string which should be freed with g_free().
1573 get_formatted_data (ModestMsgEditWindow *edit_window)
1575 ModestMsgEditWindowPrivate *priv;
1576 GString *string_buffer = g_string_new ("");
1578 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1580 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1582 modest_text_utils_hyperlinkify (string_buffer);
1584 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1586 return g_string_free (string_buffer, FALSE);
1591 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1594 const gchar *account_name;
1595 ModestMsgEditWindowPrivate *priv;
1596 TnyIterator *att_iter;
1598 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1600 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1602 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1603 g_return_val_if_fail (account_name, NULL);
1606 /* don't free these (except from) */
1607 data = g_slice_new0 (MsgData);
1608 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1610 data->account_name = g_strdup (account_name);
1611 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1612 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1613 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1614 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1615 if (priv->draft_msg) {
1616 data->draft_msg = g_object_ref (priv->draft_msg);
1617 } else if (priv->outbox_msg) {
1618 data->draft_msg = g_object_ref (priv->outbox_msg);
1620 data->draft_msg = NULL;
1623 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1625 gtk_text_buffer_get_bounds (buf, &b, &e);
1626 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1628 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1629 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1631 data->html_body = NULL;
1633 /* deep-copy the data */
1634 att_iter = tny_list_create_iterator (priv->attachments);
1635 data->attachments = NULL;
1636 while (!tny_iterator_is_done (att_iter)) {
1637 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1638 if (!(TNY_IS_MIME_PART(part))) {
1639 g_warning ("strange data in attachment list");
1640 g_object_unref (part);
1641 tny_iterator_next (att_iter);
1644 data->attachments = g_list_append (data->attachments,
1646 tny_iterator_next (att_iter);
1648 g_object_unref (att_iter);
1650 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1651 att_iter = tny_list_create_iterator (priv->images);
1652 data->images = NULL;
1653 while (!tny_iterator_is_done (att_iter)) {
1654 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1656 if (!(TNY_IS_MIME_PART(part))) {
1657 g_warning ("strange data in attachment list");
1658 g_object_unref (part);
1659 tny_iterator_next (att_iter);
1662 cid = tny_mime_part_get_content_id (part);
1664 gchar *image_tag_id;
1665 GtkTextTag *image_tag;
1667 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1668 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1669 g_free (image_tag_id);
1671 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1673 ((gtk_text_iter_has_tag (&iter, image_tag))||
1674 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1675 data->images = g_list_append (data->images,
1676 g_object_ref (part));
1678 g_object_unref (part);
1679 tny_iterator_next (att_iter);
1681 g_object_unref (att_iter);
1683 data->priority_flags = priv->priority_flags;
1690 unref_gobject (GObject *obj, gpointer data)
1692 if (!G_IS_OBJECT(obj))
1694 g_object_unref (obj);
1698 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1701 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1709 g_free (data->from);
1710 g_free (data->subject);
1711 g_free (data->plain_body);
1712 g_free (data->html_body);
1713 g_free (data->account_name);
1715 if (data->draft_msg != NULL) {
1716 g_object_unref (data->draft_msg);
1717 data->draft_msg = NULL;
1720 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1721 g_list_free (data->attachments);
1722 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1723 g_list_free (data->images);
1725 g_slice_free (MsgData, data);
1729 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1731 guint64 *parts_size)
1733 ModestMsgEditWindowPrivate *priv;
1735 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1737 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1739 /* TODO: add images */
1740 *parts_size += priv->images_size;
1741 *parts_count += priv->images_count;
1746 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1749 ModestMsgEditWindowPrivate *priv = NULL;
1750 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1752 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1754 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1756 return MODEST_MSG_EDIT_FORMAT_HTML;
1758 return MODEST_MSG_EDIT_FORMAT_TEXT;
1762 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1763 ModestMsgEditFormat format)
1765 ModestMsgEditWindowPrivate *priv;
1767 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1768 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1771 case MODEST_MSG_EDIT_FORMAT_HTML:
1772 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1774 case MODEST_MSG_EDIT_FORMAT_TEXT:
1775 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1778 g_return_if_reached ();
1782 ModestMsgEditFormatState *
1783 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1785 ModestMsgEditFormatState *format_state = NULL;
1786 ModestMsgEditWindowPrivate *priv;
1787 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1789 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1790 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1792 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1794 format_state = g_new0 (ModestMsgEditFormatState, 1);
1795 format_state->bold = buffer_format->bold&0x1;
1796 format_state->italics = buffer_format->italic&0x1;
1797 format_state->bullet = buffer_format->bullet&0x1;
1798 format_state->color = buffer_format->color;
1799 format_state->font_size = buffer_format->font_size;
1800 format_state->font_family = wp_get_font_name (buffer_format->font);
1801 format_state->justification = buffer_format->justification;
1802 g_free (buffer_format);
1804 return format_state;
1809 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1810 const ModestMsgEditFormatState *format_state)
1812 ModestMsgEditWindowPrivate *priv;
1813 WPTextBufferFormat *buffer_format;
1814 WPTextBufferFormat *current_format;
1816 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1817 g_return_if_fail (format_state != NULL);
1819 buffer_format = g_new0 (WPTextBufferFormat, 1);
1820 current_format = g_new0 (WPTextBufferFormat, 1);
1822 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1823 gtk_widget_grab_focus (priv->msg_body);
1824 buffer_format->bold = (format_state->bold != FALSE);
1825 buffer_format->italic = (format_state->italics != FALSE);
1826 buffer_format->color = format_state->color;
1827 buffer_format->font_size = format_state->font_size;
1828 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1829 buffer_format->justification = format_state->justification;
1830 buffer_format->bullet = format_state->bullet;
1832 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1834 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1835 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1836 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1837 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1838 buffer_format->cs.font = (buffer_format->font != current_format->font);
1839 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1840 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1842 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1843 if (buffer_format->cs.bold) {
1844 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1845 GINT_TO_POINTER (buffer_format->bold&0x1));
1847 if (buffer_format->cs.italic) {
1848 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1849 GINT_TO_POINTER (buffer_format->italic&0x1));
1851 if (buffer_format->cs.color) {
1852 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1853 GINT_TO_POINTER (&(buffer_format->color)));
1855 if (buffer_format->cs.font_size) {
1856 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1857 GINT_TO_POINTER (buffer_format->font_size));
1859 if (buffer_format->cs.justification) {
1860 switch (buffer_format->justification) {
1861 case GTK_JUSTIFY_LEFT:
1862 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1863 GINT_TO_POINTER(TRUE));
1865 case GTK_JUSTIFY_CENTER:
1866 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1867 GINT_TO_POINTER(TRUE));
1869 case GTK_JUSTIFY_RIGHT:
1870 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1871 GINT_TO_POINTER(TRUE));
1878 if (buffer_format->cs.font) {
1879 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1880 GINT_TO_POINTER (buffer_format->font));
1882 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1883 if (buffer_format->cs.bullet) {
1884 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1885 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1887 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1889 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1891 g_free (buffer_format);
1892 g_free (current_format);
1894 /* Check dimming rules */
1895 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1896 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1900 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1902 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1904 ModestWindowPrivate *parent_priv;
1905 ModestMsgEditWindowPrivate *priv;
1907 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1908 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1910 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1911 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1912 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1913 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1915 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1916 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1917 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1920 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1922 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1923 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1925 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1926 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1928 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1929 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1932 switch (buffer_format->justification)
1934 case GTK_JUSTIFY_LEFT:
1935 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1937 case GTK_JUSTIFY_CENTER:
1938 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1940 case GTK_JUSTIFY_RIGHT:
1941 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1948 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1950 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1951 G_CALLBACK (modest_msg_edit_window_color_button_change),
1953 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1954 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1955 G_CALLBACK (modest_msg_edit_window_color_button_change),
1958 if (priv->current_size_index != buffer_format->font_size) {
1962 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
1963 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
1967 priv->current_size_index = buffer_format->font_size;
1969 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
1970 markup = g_strconcat ("<span font_family='Sans'>",
1971 size_text, "</span>", NULL);
1973 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1977 gtk_tree_path_free (path);
1980 if (priv->current_face_index != buffer_format->font) {
1984 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
1985 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
1989 priv->current_face_index = buffer_format->font;
1990 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
1991 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
1992 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1999 g_free (buffer_format);
2003 #ifdef MODEST_HILDON_VERSION_0
2005 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2008 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2009 ModestMsgEditWindowPrivate *priv;
2010 GtkWidget *dialog = NULL;
2012 GdkColor *new_color = NULL;
2014 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2015 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2017 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2018 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2019 g_free (buffer_format);
2021 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2022 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2023 if (new_color != NULL) {
2024 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2025 (gpointer) new_color);
2028 gtk_widget_destroy (dialog);
2033 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2036 ModestMsgEditWindowPrivate *priv;
2037 GtkWidget *dialog = NULL;
2039 GdkColor *old_color = NULL;
2040 const GdkColor *new_color = NULL;
2042 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2043 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2045 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2046 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2048 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2049 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2050 if (new_color != NULL)
2051 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2053 gtk_widget_destroy (dialog);
2059 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2062 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2063 ModestMsgEditWindowPrivate *priv;
2064 GtkWidget *dialog = NULL;
2066 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2067 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2069 dialog = hildon_color_chooser_new ();
2070 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2071 g_free (buffer_format);
2073 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2075 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2076 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2079 gtk_widget_destroy (dialog);
2084 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2087 ModestMsgEditWindowPrivate *priv;
2088 GtkWidget *dialog = NULL;
2089 GdkColor *old_color = NULL;
2091 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2092 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2094 dialog = hildon_color_chooser_new ();
2095 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2097 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2099 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2100 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2102 gtk_widget_destroy (dialog);
2105 #endif /*!MODEST_HILDON_VERSION_0*/
2110 create_stream_for_uri (const gchar* uri)
2115 TnyStream *result = NULL;
2117 GnomeVFSHandle *handle = NULL;
2118 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2119 if (test == GNOME_VFS_OK) {
2120 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2121 /* Streams over OBEX (Bluetooth) are not seekable but
2122 * we expect them to be (we might need to read them
2123 * several times). So if this is a Bluetooth URI just
2124 * read the whole file into memory (this is not a fast
2125 * protocol so we can assume that these files are not
2126 * going to be very big) */
2127 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2128 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2129 TnyStream *memstream = tny_camel_mem_stream_new ();
2130 tny_stream_write_to_stream (vfssstream, memstream);
2131 g_object_unref (vfssstream);
2134 result = vfssstream;
2142 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2145 ModestMsgEditWindowPrivate *priv;
2146 GtkWidget *dialog = NULL;
2148 GSList *uris = NULL;
2149 GSList *uri_node = NULL;
2151 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2153 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2154 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2155 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2157 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2159 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2160 GTK_WINDOW (dialog), GTK_WINDOW (window));
2162 response = gtk_dialog_run (GTK_DIALOG (dialog));
2164 case GTK_RESPONSE_OK:
2165 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2170 gtk_widget_destroy (dialog);
2172 g_object_ref (window);
2173 /* The operation could take some time so allow the dialog to be closed */
2174 while (gtk_events_pending ())
2175 gtk_main_iteration ();
2177 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2179 GnomeVFSHandle *handle = NULL;
2180 GnomeVFSResult result;
2181 GtkTextIter position;
2182 GtkTextMark *insert_mark;
2184 uri = (const gchar *) uri_node->data;
2185 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2186 if (result == GNOME_VFS_OK) {
2188 GnomeVFSFileInfo *info;
2189 gchar *filename, *basename, *escaped_filename;
2190 TnyMimePart *mime_part;
2192 const gchar *mime_type = NULL;
2193 GnomeVFSURI *vfs_uri;
2194 guint64 stream_size;
2196 gnome_vfs_close (handle);
2197 vfs_uri = gnome_vfs_uri_new (uri);
2199 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2200 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2201 g_free (escaped_filename);
2202 gnome_vfs_uri_unref (vfs_uri);
2203 info = gnome_vfs_file_info_new ();
2205 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2206 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2208 mime_type = gnome_vfs_file_info_get_mime_type (info);
2210 mime_part = tny_platform_factory_new_mime_part
2211 (modest_runtime_get_platform_factory ());
2213 TnyStream *stream = create_stream_for_uri (uri);
2215 if (stream == NULL) {
2217 modest_platform_information_banner (NULL, NULL,
2218 _FM("sfil_ib_opening_not_allowed"));
2220 g_object_unref (mime_part);
2221 gnome_vfs_file_info_unref (info);
2225 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2227 content_id = g_strdup_printf ("%d", priv->next_cid);
2228 tny_mime_part_set_content_id (mime_part, content_id);
2229 g_free (content_id);
2232 basename = g_path_get_basename (filename);
2233 tny_mime_part_set_filename (mime_part, basename);
2236 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2238 if (pixbuf != NULL) {
2239 priv->images_size += stream_size;
2240 priv->images_count ++;
2241 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2242 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2243 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2244 tny_mime_part_get_content_id (mime_part), pixbuf);
2245 g_object_unref (pixbuf);
2247 tny_list_prepend (priv->images, (GObject *) mime_part);
2248 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2250 modest_platform_information_banner (NULL, NULL,
2251 _("mail_ib_file_operation_failed"));
2255 g_object_unref (mime_part);
2256 gnome_vfs_file_info_unref (info);
2260 g_object_unref (window);
2264 on_attach_file_response (GtkDialog *dialog,
2268 GSList *uris = NULL;
2270 GnomeVFSFileSize total_size, allowed_size;
2271 ModestMsgEditWindow *window;
2272 ModestMsgEditWindowPrivate *priv;
2277 case GTK_RESPONSE_OK:
2278 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2284 window = MODEST_MSG_EDIT_WINDOW (user_data);
2285 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2287 /* allowed size is the maximum size - what's already there */
2288 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2289 &att_num, &att_size);
2290 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2293 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2295 const gchar *uri = (const gchar *) uri_node->data;
2298 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2300 if (total_size > allowed_size) {
2301 g_warning ("%s: total size: %u",
2302 __FUNCTION__, (unsigned int)total_size);
2305 allowed_size -= total_size;
2307 g_slist_foreach (uris, (GFunc) g_free, NULL);
2308 g_slist_free (uris);
2310 gtk_widget_destroy (GTK_WIDGET (dialog));
2314 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2316 GtkWidget *dialog = NULL;
2317 ModestMsgEditWindowPrivate *priv;
2319 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2321 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2323 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2326 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2327 GTK_FILE_CHOOSER_ACTION_OPEN);
2328 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2329 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2330 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2331 GTK_WINDOW (dialog), GTK_WINDOW (window));
2333 /* Connect to response & show */
2334 g_signal_connect (dialog, "response",
2335 G_CALLBACK (on_attach_file_response), window);
2336 gtk_widget_show (dialog);
2341 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2343 GnomeVFSFileSize allowed_size)
2346 GnomeVFSHandle *handle = NULL;
2347 ModestMsgEditWindowPrivate *priv;
2348 GnomeVFSResult result;
2349 GnomeVFSFileSize size = 0;
2350 g_return_val_if_fail (window, 0);
2351 g_return_val_if_fail (uri, 0);
2353 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2355 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2356 if (result == GNOME_VFS_OK) {
2357 TnyMimePart *mime_part;
2359 const gchar *mime_type = NULL;
2361 gchar *escaped_filename;
2364 GnomeVFSFileInfo *info;
2365 GnomeVFSURI *vfs_uri;
2367 gnome_vfs_close (handle);
2368 vfs_uri = gnome_vfs_uri_new (uri);
2371 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2372 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2373 g_free (escaped_filename);
2374 gnome_vfs_uri_unref (vfs_uri);
2376 info = gnome_vfs_file_info_new ();
2378 if (gnome_vfs_get_file_info (uri,
2380 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2382 mime_type = gnome_vfs_file_info_get_mime_type (info);
2383 mime_part = tny_platform_factory_new_mime_part
2384 (modest_runtime_get_platform_factory ());
2386 /* try to get the attachment's size; this may fail for weird
2387 * file systems, like obex, upnp... */
2388 if (allowed_size != 0 &&
2389 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2391 if (size > allowed_size) {
2392 modest_platform_information_banner (NULL, NULL,
2393 _FM("sfil_ib_opening_not_allowed"));
2398 g_warning ("%s: could not get attachment size", __FUNCTION__);
2400 stream = create_stream_for_uri (uri);
2402 if (stream == NULL) {
2404 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2406 g_object_unref (mime_part);
2408 gnome_vfs_file_info_unref (info);
2412 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2413 g_object_unref (stream);
2415 content_id = g_strdup_printf ("%d", priv->next_cid);
2416 tny_mime_part_set_content_id (mime_part, content_id);
2417 g_free (content_id);
2420 basename = g_path_get_basename (filename);
2421 tny_mime_part_set_filename (mime_part, basename);
2424 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2425 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2427 info->size == 0, info->size);
2428 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2429 gtk_widget_show_all (priv->attachments_caption);
2430 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2432 g_object_unref (mime_part);
2433 gnome_vfs_file_info_unref (info);
2440 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2443 ModestMsgEditWindowPrivate *priv;
2446 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2447 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2449 if (att_list == NULL) {
2450 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2451 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2452 g_object_unref (att_list);
2457 g_object_ref (att_list);
2460 if (tny_list_get_length (att_list) == 0) {
2461 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2463 gboolean dialog_response;
2464 gchar *message = NULL;
2465 gchar *filename = NULL;
2467 if (tny_list_get_length (att_list) == 1) {
2469 iter = tny_list_create_iterator (att_list);
2470 part = (TnyMimePart *) tny_iterator_get_current (iter);
2471 g_object_unref (iter);
2472 if (TNY_IS_MSG (part)) {
2473 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2475 filename = tny_header_dup_subject (header);
2476 g_object_unref (header);
2478 if (filename == NULL) {
2479 filename = g_strdup (_("mail_va_no_subject"));
2482 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2484 g_object_unref (part);
2486 filename = g_strdup ("");
2488 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2489 "emev_nc_delete_attachments",
2490 tny_list_get_length (att_list)), filename);
2493 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2497 if (dialog_response != GTK_RESPONSE_OK) {
2498 g_object_unref (att_list);
2502 for (iter = tny_list_create_iterator (att_list);
2503 !tny_iterator_is_done (iter);
2504 tny_iterator_next (iter)) {
2505 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2506 const gchar *att_id;
2507 tny_list_remove (priv->attachments, (GObject *) mime_part);
2509 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2511 if (tny_list_get_length (priv->attachments) == 0)
2512 gtk_widget_hide (priv->attachments_caption);
2513 att_id = tny_mime_part_get_content_id (mime_part);
2515 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2517 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2518 g_object_unref (mime_part);
2520 g_object_unref (iter);
2523 g_object_unref (att_list);
2525 /* if the last attachment has been removed, focus the Subject: field */
2526 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2527 gtk_widget_grab_focus (priv->subject_field);
2531 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2534 ModestMsgEditWindowPrivate *priv;
2535 GdkColor *new_color;
2536 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2538 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2539 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2542 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2544 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2546 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2548 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2553 font_size_clicked (GtkToolButton *button,
2554 ModestMsgEditWindow *window)
2556 ModestMsgEditWindowPrivate *priv;
2557 GtkWidget *selector, *dialog;
2559 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2561 selector = hildon_touch_selector_new ();
2562 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2563 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2565 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2566 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2568 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2572 WPTextBufferFormat format;
2574 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2576 memset (&format, 0, sizeof (format));
2577 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2579 format.cs.font_size = TRUE;
2580 format.cs.text_position = TRUE;
2581 format.cs.font = TRUE;
2582 format.font_size = new_index;
2583 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2585 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2586 GINT_TO_POINTER (new_index)))
2587 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2589 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2590 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2591 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2592 size_text, "</span>", NULL);
2594 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2598 gtk_widget_destroy (dialog);
2600 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2605 font_face_clicked (GtkToolButton *button,
2606 ModestMsgEditWindow *window)
2608 ModestMsgEditWindowPrivate *priv;
2609 GtkWidget *selector, *dialog;
2610 GtkCellRenderer *renderer;
2612 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2614 selector = hildon_touch_selector_new ();
2615 renderer = gtk_cell_renderer_text_new ();
2616 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2617 renderer, "family", 0, "text", 0, NULL);
2618 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2620 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2621 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2623 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2624 gint new_font_index;
2628 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2629 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2630 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2634 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2636 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2637 GINT_TO_POINTER(new_font_index)))
2638 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2640 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2641 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2643 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2647 gtk_tree_path_free (path);
2650 gtk_widget_destroy (dialog);
2652 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2657 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2660 ModestMsgEditWindowPrivate *priv = NULL;
2661 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2663 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2664 if (!priv->update_caption_visibility)
2667 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2669 gtk_widget_show (priv->cc_caption);
2671 gtk_widget_hide (priv->cc_caption);
2673 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2677 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2680 ModestMsgEditWindowPrivate *priv = NULL;
2681 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2683 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2684 if (!priv->update_caption_visibility)
2687 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2689 gtk_widget_show (priv->bcc_caption);
2691 gtk_widget_hide (priv->bcc_caption);
2693 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2697 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2698 ModestRecptEditor *editor)
2700 ModestMsgEditWindowPrivate *priv;
2702 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2703 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2705 /* we check for low-mem; in that case, show a warning, and don't allow
2706 * for the addressbook
2708 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2711 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2713 if (editor == NULL) {
2714 GtkWidget *view_focus;
2715 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2717 /* This code should be kept in sync with ModestRecptEditor. The
2718 textview inside the recpt editor is the one that really gets the
2719 focus. As it's inside a scrolled window, and this one inside the
2720 hbox recpt editor inherits from, we'll need to go up in the
2721 hierarchy to know if the text view is part of the recpt editor
2722 or if it's a different text entry */
2724 if (gtk_widget_get_parent (view_focus)) {
2725 GtkWidget *first_parent;
2727 first_parent = gtk_widget_get_parent (view_focus);
2728 if (gtk_widget_get_parent (first_parent) &&
2729 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2730 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2735 editor = MODEST_RECPT_EDITOR (priv->to_field);
2739 modest_address_book_select_addresses (editor);
2744 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2746 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2748 modest_msg_edit_window_open_addressbook (window, NULL);
2752 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2753 gboolean show_toolbar)
2755 ModestWindowPrivate *parent_priv;
2757 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2758 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2760 /* We can not just use the code of
2761 modest_msg_edit_window_setup_toolbar because it has a
2762 mixture of both initialization and creation code. */
2764 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2766 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2770 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2771 TnyHeaderFlags priority_flags)
2773 ModestMsgEditWindowPrivate *priv;
2774 ModestWindowPrivate *parent_priv;
2776 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2778 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2779 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2781 if (priv->priority_flags != priority_flags) {
2782 GtkAction *priority_action = NULL;
2784 priv->priority_flags = priority_flags;
2786 switch (priority_flags) {
2787 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2788 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2789 MODEST_HEADER_ICON_HIGH,
2790 HILDON_ICON_SIZE_SMALL);
2791 gtk_widget_show (priv->priority_icon);
2792 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2793 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2795 case TNY_HEADER_FLAG_LOW_PRIORITY:
2796 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2797 MODEST_HEADER_ICON_LOW,
2798 HILDON_ICON_SIZE_SMALL);
2799 gtk_widget_show (priv->priority_icon);
2800 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2801 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2804 gtk_widget_hide (priv->priority_icon);
2805 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2806 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2809 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2810 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2812 gtk_widget_queue_resize (priv->subject_box);
2816 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2819 ModestMsgEditWindowPrivate *priv;
2820 ModestWindowPrivate *parent_priv;
2821 gint current_format;
2823 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2825 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2826 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2828 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2829 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2831 if (current_format != file_format) {
2832 switch (file_format) {
2833 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2834 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2835 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2837 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2841 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2842 response = gtk_dialog_run (GTK_DIALOG (dialog));
2843 gtk_widget_destroy (dialog);
2844 if (response == GTK_RESPONSE_OK) {
2845 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2847 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2848 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2853 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2854 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2855 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2860 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2863 ModestMsgEditWindowPrivate *priv;
2864 WPTextBufferFormat oldfmt, fmt;
2865 gint old_position = 0;
2869 GdkColor *color = NULL;
2870 gboolean bold, bold_set, italic, italic_set;
2871 gboolean underline, underline_set;
2872 gboolean strikethrough, strikethrough_set;
2873 gboolean position_set;
2874 gboolean font_size_set, font_set, color_set;
2877 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2878 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2880 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2881 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2882 GTK_WINDOW(dialog), GTK_WINDOW (window));
2884 /* First we get the currently selected font information */
2885 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2887 switch (oldfmt.text_position) {
2888 case TEXT_POSITION_NORMAL:
2891 case TEXT_POSITION_SUPERSCRIPT:
2899 g_object_set (G_OBJECT (dialog),
2900 "bold", oldfmt.bold != FALSE,
2901 "bold-set", !oldfmt.cs.bold,
2902 "underline", oldfmt.underline != FALSE,
2903 "underline-set", !oldfmt.cs.underline,
2904 "italic", oldfmt.italic != FALSE,
2905 "italic-set", !oldfmt.cs.italic,
2906 "strikethrough", oldfmt.strikethrough != FALSE,
2907 "strikethrough-set", !oldfmt.cs.strikethrough,
2908 "color", &oldfmt.color,
2909 "color-set", !oldfmt.cs.color,
2910 "size", wp_font_size[oldfmt.font_size],
2911 "size-set", !oldfmt.cs.font_size,
2912 "position", old_position,
2913 "position-set", !oldfmt.cs.text_position,
2914 "family", wp_get_font_name (oldfmt.font),
2915 "family-set", !oldfmt.cs.font,
2918 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2919 GTK_WINDOW (dialog), GTK_WINDOW (window));
2920 gtk_widget_show_all (dialog);
2921 priv->font_dialog = dialog;
2922 response = gtk_dialog_run (GTK_DIALOG (dialog));
2923 priv->font_dialog = NULL;
2924 if (response == GTK_RESPONSE_OK) {
2926 g_object_get( dialog,
2928 "bold-set", &bold_set,
2929 "underline", &underline,
2930 "underline-set", &underline_set,
2932 "italic-set", &italic_set,
2933 "strikethrough", &strikethrough,
2934 "strikethrough-set", &strikethrough_set,
2936 "color-set", &color_set,
2938 "size-set", &font_size_set,
2939 "family", &font_name,
2940 "family-set", &font_set,
2941 "position", &position,
2942 "position-set", &position_set,
2947 if (response == GTK_RESPONSE_OK) {
2948 memset(&fmt, 0, sizeof(fmt));
2954 fmt.italic = italic;
2955 fmt.cs.italic = TRUE;
2957 if (underline_set) {
2958 fmt.underline = underline;
2959 fmt.cs.underline = TRUE;
2961 if (strikethrough_set) {
2962 fmt.strikethrough = strikethrough;
2963 fmt.cs.strikethrough = TRUE;
2968 ? TEXT_POSITION_NORMAL
2969 : ( ( position == 1 )
2970 ? TEXT_POSITION_SUPERSCRIPT
2971 : TEXT_POSITION_SUBSCRIPT );
2972 fmt.cs.text_position = TRUE;
2973 fmt.font_size = oldfmt.font_size;
2977 fmt.cs.color = TRUE;
2980 fmt.font = wp_get_font_index(font_name,
2985 if (font_size_set) {
2986 fmt.cs.font_size = TRUE;
2987 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2989 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2990 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2992 gtk_widget_destroy (dialog);
2994 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2998 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3000 ModestMsgEditWindowPrivate *priv;
3002 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3003 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3005 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3007 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3008 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3012 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3014 ModestMsgEditWindowPrivate *priv;
3016 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3017 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3019 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3021 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3022 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3027 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3029 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3031 priv->can_undo = can_undo;
3035 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3037 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3039 priv->can_redo = can_redo;
3043 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3045 ModestMsgEditWindowPrivate *priv;
3046 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3047 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3049 return priv->can_undo;
3053 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3055 ModestMsgEditWindowPrivate *priv;
3056 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3057 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3059 return priv->can_redo;
3064 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3067 GtkTextIter match_start, match_end;
3069 if (image_id == NULL)
3072 gtk_text_buffer_get_start_iter (buffer, &iter);
3074 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3075 GSList *tags = gtk_text_iter_get_tags (&match_start);
3077 for (node = tags; node != NULL; node = g_slist_next (node)) {
3078 GtkTextTag *tag = (GtkTextTag *) node->data;
3079 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3080 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3081 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3083 offset = gtk_text_iter_get_offset (&match_start);
3084 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3085 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3089 gtk_text_iter_forward_char (&iter);
3094 message_is_empty (ModestMsgEditWindow *window)
3096 ModestMsgEditWindowPrivate *priv = NULL;
3098 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3099 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3101 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3102 * so we can ignore markup.
3104 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3107 count = gtk_text_buffer_get_char_count (buf);
3113 msg_body_focus (GtkWidget *focus,
3114 GdkEventFocus *event,
3118 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3119 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3120 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3125 recpt_field_changed (GtkTextBuffer *buffer,
3126 ModestMsgEditWindow *editor)
3128 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3129 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3133 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3135 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3136 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3140 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3143 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3144 GtkTextBuffer *buffer;
3146 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3147 gtk_text_buffer_set_modified (buffer, modified);
3148 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3149 gtk_text_buffer_set_modified (buffer, modified);
3150 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3151 gtk_text_buffer_set_modified (buffer, modified);
3152 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3156 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3158 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3159 const char *account_name;
3160 GtkTextBuffer *buffer;
3162 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3163 if (gtk_text_buffer_get_modified (buffer))
3165 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3166 if (gtk_text_buffer_get_modified (buffer))
3168 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3169 if (gtk_text_buffer_get_modified (buffer))
3171 if (gtk_text_buffer_get_modified (priv->text_buffer))
3173 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3174 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3185 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3187 ModestMsgEditWindowPrivate *priv = NULL;
3189 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3190 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3192 /* check if there's no recipient added */
3193 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3194 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3195 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3196 /* no recipient contents, then select contacts */
3197 modest_msg_edit_window_open_addressbook (window, NULL);
3201 g_object_ref (window);
3202 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3203 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3204 g_object_unref (window);
3207 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3208 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3209 g_object_unref (window);
3212 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3213 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3214 g_object_unref (window);
3218 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3219 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3220 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3221 g_object_unref (window);
3228 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3229 ModestMsgEditWindow *window)
3231 modest_msg_edit_window_offer_attach_file (window);
3235 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3237 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3239 return priv->clipboard_text;
3243 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3245 ModestMsgEditWindow *window)
3247 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3248 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3251 /* It could happen that the window was already closed */
3252 if (!GTK_WIDGET_VISIBLE (window))
3255 g_object_ref (window);
3256 text = gtk_clipboard_wait_for_text (selection_clipboard);
3258 if (priv->clipboard_text != NULL) {
3259 g_free (priv->clipboard_text);
3261 priv->clipboard_text = text;
3263 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3265 g_object_unref (window);
3268 static gboolean clipboard_owner_change_idle (gpointer userdata)
3270 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3271 ModestMsgEditWindowPrivate *priv;
3273 gdk_threads_enter ();
3274 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3275 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3277 priv->clipboard_owner_idle = 0;
3278 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3279 gdk_threads_leave ();
3285 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3287 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3288 if (priv->clipboard_owner_idle == 0) {
3289 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3290 clipboard_owner_change_idle,
3291 g_object_ref (window),
3297 subject_field_move_cursor (GtkEntry *entry,
3298 GtkMovementStep step,
3303 /* It could happen that the window was already closed */
3304 if (!GTK_WIDGET_VISIBLE (window))
3307 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3311 update_window_title (ModestMsgEditWindow *window)
3313 ModestMsgEditWindowPrivate *priv = NULL;
3314 const gchar *subject;
3316 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3317 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3318 if (subject == NULL || subject[0] == '\0')
3319 subject = _("mail_va_new_email");
3321 gtk_window_set_title (GTK_WINDOW (window), subject);
3326 subject_field_changed (GtkEditable *editable,
3327 ModestMsgEditWindow *window)
3329 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3330 update_window_title (window);
3331 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3332 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3333 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3337 subject_field_insert_text (GtkEditable *editable,
3339 gint new_text_length,
3341 ModestMsgEditWindow *window)
3343 GString *result = g_string_new ("");
3345 gint result_len = 0;
3346 const gchar *entry_text = NULL;
3349 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3350 old_length = g_utf8_strlen (entry_text, -1);
3352 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3353 gunichar c = g_utf8_get_char_validated (current, 8);
3354 /* Invalid unichar, stop */
3360 result = g_string_append_unichar (result, c);
3364 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3365 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3368 /* Prevent endless recursion */
3369 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3370 g_signal_emit_by_name (editable, "insert-text",
3371 (gpointer) result->str, (gpointer) result->len,
3372 (gpointer) position, (gpointer) window);
3373 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3377 if (result_len + old_length > 1000) {
3378 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3379 _CS("ckdg_ib_maximum_characters_reached"));
3381 g_string_free (result, TRUE);
3385 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3388 ModestMsgEditWindowPrivate *priv = NULL;
3390 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3391 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3393 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3396 gtk_widget_show_all (priv->find_toolbar);
3397 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3399 gtk_widget_hide_all (priv->find_toolbar);
3400 gtk_widget_grab_focus (priv->msg_body);
3405 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3407 GtkTextIter *match_start,
3408 GtkTextIter *match_end)
3410 GtkTextIter end_iter;
3411 gchar *str_casefold;
3414 gchar *range_casefold;
3417 gboolean result = FALSE;
3424 gtk_text_iter_forward_to_end (&end_iter);
3426 str_casefold = g_utf8_casefold (str, -1);
3427 str_chars_n = strlen (str);
3429 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3430 range_casefold = g_utf8_casefold (range_text, -1);
3431 range_chars_n = strlen (range_casefold);
3433 if (range_chars_n < str_chars_n) {
3434 g_free (str_casefold);
3435 g_free (range_text);
3436 g_free (range_casefold);
3440 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3441 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3442 if (!g_utf8_collate (range_subtext, str_casefold)) {
3443 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3445 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3446 match_start, match_end, NULL);
3447 g_free (found_text);
3449 g_free (range_subtext);
3453 g_free (str_casefold);
3454 g_free (range_text);
3455 g_free (range_casefold);
3462 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3463 ModestMsgEditWindow *window)
3465 gchar *current_search = NULL;
3466 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3468 GtkTextIter selection_start, selection_end;
3469 GtkTextIter match_start, match_end;
3470 gboolean continue_search = FALSE;
3472 if (message_is_empty (window)) {
3473 g_free (priv->last_search);
3474 priv->last_search = NULL;
3475 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3479 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3480 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3481 g_free (current_search);
3482 g_free (priv->last_search);
3483 priv->last_search = NULL;
3484 /* Information banner about empty search */
3485 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3489 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3490 continue_search = TRUE;
3492 g_free (priv->last_search);
3493 priv->last_search = g_strdup (current_search);
3496 if (continue_search) {
3497 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3498 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3499 &match_start, &match_end);
3501 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3503 GtkTextIter buffer_start;
3504 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3505 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3506 &match_start, &match_end);
3508 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3511 /* Mark as selected the string found in search */
3513 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3514 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3515 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3517 g_free (priv->last_search);
3518 priv->last_search = NULL;
3520 g_free (current_search);
3524 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3526 ModestMsgEditWindowPrivate *priv;
3528 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3533 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3536 ModestMsgEditWindowPrivate *priv;
3538 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3543 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3544 ModestMsgEditWindow *window)
3546 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3550 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3553 ModestMsgEditWindowPrivate *priv;
3554 TnyHeader *header = NULL;
3556 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3557 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3559 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3560 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3562 if (priv->draft_msg != NULL) {
3563 g_object_unref (priv->draft_msg);
3566 if (draft != NULL) {
3567 g_object_ref (draft);
3568 header = tny_msg_get_header (draft);
3569 if (priv->msg_uid) {
3570 g_free (priv->msg_uid);
3571 priv->msg_uid = NULL;
3573 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3574 if (GTK_WIDGET_REALIZED (window)) {
3575 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3576 gtk_widget_destroy (GTK_WIDGET (window));
3582 priv->draft_msg = draft;
3586 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3587 GtkTextIter *start, GtkTextIter *end,
3590 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3591 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3594 if (tag == NULL) return;
3595 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3596 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3597 replace_with_images (window, priv->images);
3602 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3605 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3607 g_return_if_fail (TNY_IS_MIME_PART (part));
3608 tny_list_prepend (priv->attachments, (GObject *) part);
3609 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3610 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3611 gtk_widget_show_all (priv->attachments_caption);
3612 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3616 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3618 ModestMsgEditWindowPrivate *priv;
3620 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3621 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3623 return priv->msg_uid;
3627 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3628 ModestMsgEditWindowWidgetType widget_type)
3630 ModestMsgEditWindowPrivate *priv;
3632 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3633 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3635 switch (widget_type) {
3636 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3637 return priv->msg_body;
3639 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3640 return priv->to_field;
3642 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3643 return priv->cc_field;
3645 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3646 return priv->bcc_field;
3648 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3649 return priv->subject_field;
3651 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3652 return priv->attachments_view;
3660 remove_tags (WPTextBuffer *buffer)
3662 GtkTextIter start, end;
3664 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3665 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3667 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3671 on_account_removed (TnyAccountStore *account_store,
3672 TnyAccount *account,
3675 /* Do nothing if it's a store account, because we use the
3676 transport to send the messages */
3677 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3678 const gchar *parent_acc = NULL;
3679 const gchar *our_acc = NULL;
3681 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3682 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3683 /* Close this window if I'm showing a message of the removed account */
3684 if (strcmp (parent_acc, our_acc) == 0)
3685 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3690 from_field_changed (HildonPickerButton *button,
3691 ModestMsgEditWindow *self)
3693 ModestMsgEditWindowPrivate *priv;
3694 gboolean has_old_signature, has_new_signature;
3696 GtkTextIter match_start, match_end;
3697 ModestAccountMgr *mgr;
3699 gchar *full_signature;
3701 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3703 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3704 mgr = modest_runtime_get_account_mgr ();
3705 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3706 if (has_old_signature) {
3707 full_signature = g_strconcat ("\n--\n", signature, NULL);
3708 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3709 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3711 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3712 &match_start, &match_end, NULL)) {
3715 g_free (full_signature);
3719 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3720 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3721 if (has_new_signature) {
3722 full_signature = g_strconcat ("\n--\n", signature, NULL);
3723 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3724 g_free (full_signature);
3729 typedef struct _MessageSettingsHelper {
3730 ModestMsgEditWindow *window;
3731 GSList *priority_group;
3732 GSList *format_group;
3733 GtkToggleButton *current_priority;
3734 GtkToggleButton *current_format;
3735 } MessageSettingsHelper;
3738 on_priority_toggle (GtkToggleButton *button,
3739 MessageSettingsHelper *helper)
3742 ModestMsgEditWindowPrivate *priv;
3744 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3745 if (gtk_toggle_button_get_active (button)) {
3747 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3748 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3749 if ((node_button != button) &&
3750 gtk_toggle_button_get_active (node_button)) {
3751 gtk_toggle_button_set_active (node_button, FALSE);
3754 helper->current_priority = button;
3756 gboolean found = FALSE;
3757 /* If no one is active, activate it again */
3758 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3759 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3760 if (gtk_toggle_button_get_active (node_button)) {
3766 gtk_toggle_button_set_active (button, TRUE);
3772 on_format_toggle (GtkToggleButton *button,
3773 MessageSettingsHelper *helper)
3776 ModestMsgEditWindowPrivate *priv;
3778 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3779 if (gtk_toggle_button_get_active (button)) {
3781 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3782 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3783 if ((node_button != button) &&
3784 gtk_toggle_button_get_active (node_button)) {
3785 gtk_toggle_button_set_active (node_button, FALSE);
3788 helper->current_format = button;
3790 gboolean found = FALSE;
3791 /* If no one is active, activate it again */
3792 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3793 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3794 if (gtk_toggle_button_get_active (node_button)) {
3800 gtk_toggle_button_set_active (button, TRUE);
3807 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3812 GtkWidget *priority_hbox;
3813 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3814 GtkWidget *captioned;
3815 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3816 GtkWidget *format_hbox;
3817 GtkWidget *html_toggle, *text_toggle;
3818 ModestMsgEditWindowPrivate *priv;
3819 MessageSettingsHelper helper = {0,};
3821 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3822 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3823 helper.window = window;
3824 helper.priority_group = NULL;
3825 helper.format_group = NULL;
3827 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3828 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3830 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3831 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3832 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3833 vbox = gtk_vbox_new (FALSE, 0);
3834 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
3835 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
3836 gtk_container_add (GTK_CONTAINER (align), vbox);
3837 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
3838 gtk_widget_show (align);
3839 gtk_widget_show (vbox);
3841 /* Priority toggles */
3842 priority_hbox = gtk_hbox_new (TRUE, 0);
3843 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3844 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3845 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3846 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3847 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3848 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3849 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3850 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3851 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3852 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3853 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3854 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3855 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3856 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3857 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3858 gtk_widget_show_all (priority_hbox);
3859 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3860 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3861 gtk_widget_show (captioned);
3862 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3864 /* format toggles */
3865 format_hbox = gtk_hbox_new (TRUE, 0);
3866 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3867 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3868 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3869 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3870 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3871 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3872 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3873 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3874 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3875 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3876 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3877 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3878 gtk_widget_show_all (format_hbox);
3879 gtk_widget_show (format_hbox);
3880 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3883 g_object_unref (title_sizegroup);
3884 g_object_unref (value_sizegroup);
3886 /* Set current values */
3887 switch (priv->priority_flags) {
3888 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3889 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3890 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3892 case TNY_HEADER_FLAG_LOW_PRIORITY:
3893 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3894 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3897 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3898 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3902 switch (modest_msg_edit_window_get_format (window)) {
3903 case MODEST_MSG_EDIT_FORMAT_TEXT:
3904 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3905 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3907 case MODEST_MSG_EDIT_FORMAT_HTML:
3909 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3910 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3914 /* Signal connects */
3915 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3916 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3917 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3918 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3919 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3921 /* Save settings if the user clicked on done */
3922 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3923 TnyHeaderFlags flags;
3924 ModestMsgEditFormat old_format, new_format;
3926 /* Set priority flags */
3927 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3928 if (priv->priority_flags != flags)
3929 modest_msg_edit_window_set_priority_flags (window, flags);
3931 /* Set edit format */
3932 old_format = modest_msg_edit_window_get_format (window);
3933 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3934 if (old_format != new_format) {
3935 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3936 modest_msg_edit_window_set_file_format (window, file_format);
3940 gtk_widget_destroy (dialog);
3941 g_slist_free (helper.priority_group);
3945 on_message_settings (GtkAction *action,
3946 ModestMsgEditWindow *window)
3948 modest_msg_edit_window_show_msg_settings_dialog (window);
3952 on_cc_button_toggled (HildonCheckButton *button,
3953 ModestMsgEditWindow *window)
3955 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3957 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3958 hildon_check_button_get_active (button));
3962 on_bcc_button_toggled (HildonCheckButton *button,
3963 ModestMsgEditWindow *window)
3965 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3967 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3968 hildon_check_button_get_active (button));
3972 setup_menu (ModestMsgEditWindow *self)
3974 ModestMsgEditWindowPrivate *priv = NULL;
3976 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3978 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3980 /* Settings menu buttons */
3981 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3982 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3984 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3985 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3986 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3988 priv->cc_button = hildon_check_button_new (0);
3989 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3990 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3992 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3994 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3995 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3996 priv->bcc_button = hildon_check_button_new (0);
3997 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3998 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4000 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4002 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4003 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4005 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4006 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4007 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4008 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4009 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4010 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4011 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4012 APP_MENU_CALLBACK (on_message_settings),
4014 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4015 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),