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 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
490 correct_scroll_without_drag_check (win, TRUE);
492 priv->scroll_drag_timeout_id = 0;
498 correct_scroll_without_drag_check_idle (gpointer userdata)
500 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
501 ModestMsgEditWindowPrivate *priv;
503 GdkRectangle rectangle;
504 gint offset_min, offset_max;
508 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
510 insert = gtk_text_buffer_get_insert (priv->text_buffer);
511 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
513 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
514 offset_min = priv->msg_body->allocation.y + rectangle.y;
515 offset_max = offset_min + rectangle.height;
517 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
518 offset_min = MAX (offset_min - 48, 0);
519 offset_max = MIN (offset_max + 48, vadj->upper);
521 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
523 priv->correct_scroll_idle = 0;
528 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
530 ModestMsgEditWindowPrivate *priv;
532 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
534 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
537 if (priv->correct_scroll_idle > 0) {
541 priv->correct_scroll_idle = g_idle_add ((GSourceFunc) correct_scroll_without_drag_check_idle,
546 correct_scroll (ModestMsgEditWindow *w)
548 ModestMsgEditWindowPrivate *priv;
550 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
551 if (gtk_grab_get_current () == priv->msg_body) {
552 if (priv->scroll_drag_timeout_id == 0) {
553 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
559 correct_scroll_without_drag_check (w, TRUE);
563 text_buffer_end_user_action (GtkTextBuffer *buffer,
564 ModestMsgEditWindow *userdata)
567 correct_scroll (userdata);
571 text_buffer_mark_set (GtkTextBuffer *buffer,
574 ModestMsgEditWindow *userdata)
576 gtk_text_buffer_begin_user_action (buffer);
577 gtk_text_buffer_end_user_action (buffer);
581 cut_clipboard_check (GtkTextView *text_view,
584 GtkTextBuffer *buffer;
586 buffer = gtk_text_view_get_buffer (text_view);
587 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
588 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
593 copy_clipboard_check (GtkTextView *text_view,
596 GtkTextBuffer *buffer;
598 buffer = gtk_text_view_get_buffer (text_view);
599 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
600 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
605 attachment_deleted (ModestAttachmentsView *attachments_view,
608 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
613 connect_signals (ModestMsgEditWindow *obj)
615 ModestMsgEditWindowPrivate *priv;
617 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
619 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
620 G_CALLBACK (text_buffer_refresh_attributes), obj);
621 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
622 G_CALLBACK (text_buffer_can_undo), obj);
623 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
624 G_CALLBACK (text_buffer_can_redo), obj);
625 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
626 G_CALLBACK (body_changed), obj);
627 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
628 G_CALLBACK (body_changed), obj);
629 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
630 G_CALLBACK (text_buffer_end_user_action), obj);
631 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
632 G_CALLBACK (text_buffer_mark_set), obj);
633 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
634 G_CALLBACK (text_buffer_apply_tag), obj);
635 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
636 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
637 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
638 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
639 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
640 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
642 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
643 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
644 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
645 G_CALLBACK (from_field_changed), obj);
647 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
648 G_CALLBACK (msg_body_focus), obj);
649 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
650 G_CALLBACK (msg_body_focus), obj);
651 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
652 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
653 "changed", G_CALLBACK (recpt_field_changed), obj);
654 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
655 "changed", G_CALLBACK (recpt_field_changed), obj);
656 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
657 "changed", G_CALLBACK (recpt_field_changed), obj);
658 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
659 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
660 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
662 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
663 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
665 priv->clipboard_change_handler_id =
666 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
667 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
668 priv->default_clipboard_change_handler_id =
669 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
670 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
672 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
673 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
674 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
678 init_wp_text_view_style ()
680 static gboolean initialized = FALSE;
683 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
689 init_window (ModestMsgEditWindow *obj)
691 GtkWidget *to_caption, *subject_caption;
692 GtkWidget *main_vbox;
693 GtkWidget *add_attachment_align;
694 ModestMsgEditWindowPrivate *priv;
695 GtkActionGroup *action_group;
696 ModestWindowPrivate *parent_priv;
697 GdkPixbuf *window_icon = NULL;
698 GError *error = NULL;
700 GtkSizeGroup *title_size_group;
701 GtkSizeGroup *value_size_group;
702 GtkWidget *attachment_icon;
703 GtkWidget *window_box;
704 GtkWidget *window_align;
705 #if (GTK_MINOR_VERSION >= 10)
706 GdkAtom deserialize_type;
709 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
710 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
712 parent_priv->ui_manager = gtk_ui_manager_new();
713 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
714 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
716 /* Add common actions */
717 gtk_action_group_add_actions (action_group,
718 modest_msg_edit_action_entries,
719 G_N_ELEMENTS (modest_msg_edit_action_entries),
721 gtk_action_group_add_actions (action_group,
722 hildon2_msg_edit_action_entries,
723 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
725 gtk_action_group_add_toggle_actions (action_group,
726 modest_msg_edit_toggle_action_entries,
727 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
729 gtk_action_group_add_radio_actions (action_group,
730 modest_msg_edit_alignment_radio_action_entries,
731 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
733 G_CALLBACK (modest_ui_actions_on_change_justify),
735 gtk_action_group_add_radio_actions (action_group,
736 modest_msg_edit_priority_action_entries,
737 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
739 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
741 gtk_action_group_add_radio_actions (action_group,
742 modest_msg_edit_file_format_action_entries,
743 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
744 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
745 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
747 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
748 g_object_unref (action_group);
750 /* Load the UI definition */
751 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
754 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
755 g_clear_error (&error);
758 /* Add accelerators */
759 gtk_window_add_accel_group (GTK_WINDOW (obj),
760 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
762 parent_priv->menubar = NULL;
764 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
765 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
767 /* Note: This ModestPairList* must exist for as long as the picker
768 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
769 * so it can't know how to manage its memory. */
770 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
771 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
773 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
774 _("mail_va_from"), priv->from_field);
776 priv->to_field = modest_recpt_editor_new ();
777 priv->cc_field = modest_recpt_editor_new ();
778 priv->bcc_field = modest_recpt_editor_new ();
779 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
780 priv->priority_icon = gtk_image_new ();
781 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
782 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
783 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
784 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
785 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
786 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
787 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
788 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
789 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
790 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
791 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
792 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
793 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
794 add_attachment_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
795 gtk_alignment_set_padding (GTK_ALIGNMENT (add_attachment_align), 0, 0, MODEST_MARGIN_DEFAULT, 0);
796 gtk_container_add (GTK_CONTAINER (add_attachment_align), priv->add_attachment_button);
797 gtk_box_pack_start (GTK_BOX (priv->subject_box), add_attachment_align, FALSE, FALSE, 0);
798 priv->attachments_view = modest_attachments_view_new (NULL);
799 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
800 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
802 priv->header_box = gtk_vbox_new (FALSE, 0);
804 to_caption = modest_maemo_utils_create_captioned_with_size_type
805 (title_size_group, value_size_group,
806 _("mail_va_to"), FALSE, priv->to_field,
807 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
808 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
809 (title_size_group, value_size_group,
810 _("mail_va_cc"), FALSE, priv->cc_field,
811 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
812 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
813 (title_size_group, value_size_group,
814 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
815 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
816 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
817 _("mail_va_subject"), FALSE, priv->subject_box);
818 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
819 _("mail_va_attachment"),
821 priv->attachments_view,
822 HILDON_SIZE_AUTO_WIDTH |
823 HILDON_SIZE_AUTO_HEIGHT);
824 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
825 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
826 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
827 g_object_unref (title_size_group);
828 g_object_unref (value_size_group);
830 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
831 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
832 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
833 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
834 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
835 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
836 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
838 init_wp_text_view_style ();
840 priv->msg_body = modest_wp_text_view_new ();
843 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
844 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
845 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
846 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
847 #if (GTK_MINOR_VERSION >= 10)
848 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
849 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
851 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
852 deserialize_type, TRUE);
854 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
856 priv->find_toolbar = hildon_find_toolbar_new (NULL);
857 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
859 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
861 priv->pannable = hildon_pannable_area_new ();
863 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
864 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
865 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
867 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
868 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
869 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
871 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
872 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox),
873 hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable)));
874 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
876 window_box = gtk_vbox_new (FALSE, 0);
877 gtk_container_add (GTK_CONTAINER(obj), window_box);
879 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
881 /* Set window icon */
882 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
884 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
885 g_object_unref (window_icon);
890 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
892 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
894 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
895 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
896 priv->clipboard_change_handler_id))
897 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
898 priv->clipboard_change_handler_id);
899 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
900 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
901 priv->default_clipboard_change_handler_id))
902 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
903 priv->default_clipboard_change_handler_id);
905 if (priv->account_removed_handler_id &&
906 g_signal_handler_is_connected (modest_runtime_get_account_store (),
907 priv->account_removed_handler_id))
908 g_signal_handler_disconnect(modest_runtime_get_account_store (),
909 priv->account_removed_handler_id);
913 modest_msg_edit_window_finalize (GObject *obj)
915 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
917 /* Sanity check: shouldn't be needed, the window mgr should
918 call this function before */
919 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
921 if (priv->font_dialog != NULL) {
922 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
925 if (priv->clipboard_text != NULL) {
926 g_free (priv->clipboard_text);
927 priv->clipboard_text = NULL;
930 if (priv->draft_msg != NULL) {
931 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
932 if (TNY_IS_HEADER (header)) {
933 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
934 modest_window_mgr_unregister_header (mgr, header);
936 g_object_unref (priv->draft_msg);
937 priv->draft_msg = NULL;
939 if (priv->outbox_msg != NULL) {
940 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
941 if (TNY_IS_HEADER (header)) {
942 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
943 modest_window_mgr_unregister_header (mgr, header);
945 g_object_unref (priv->outbox_msg);
946 priv->outbox_msg = NULL;
948 if (priv->correct_scroll_idle > 0) {
949 g_source_remove (priv->correct_scroll_idle);
950 priv->correct_scroll_idle = 0;
952 if (priv->scroll_drag_timeout_id > 0) {
953 g_source_remove (priv->scroll_drag_timeout_id);
954 priv->scroll_drag_timeout_id = 0;
956 if (priv->clipboard_owner_idle > 0) {
957 g_source_remove (priv->clipboard_owner_idle);
958 priv->clipboard_owner_idle = 0;
960 if (priv->original_account_name)
961 g_free (priv->original_account_name);
962 g_free (priv->msg_uid);
963 g_free (priv->last_search);
964 g_object_unref (priv->faces_model);
965 g_object_unref (priv->sizes_model);
966 g_object_unref (priv->attachments);
967 g_object_unref (priv->images);
969 /* This had to stay alive for as long as the picker that used it: */
970 modest_pair_list_free (priv->from_field_protos);
972 G_OBJECT_CLASS(parent_class)->finalize (obj);
976 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
978 GdkPixbufLoader *loader;
981 GError *error = NULL;
985 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
987 if (loader == NULL) {
993 tny_stream_reset (TNY_STREAM (stream));
994 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
995 unsigned char read_buffer[128];
997 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
999 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1004 gdk_pixbuf_loader_close (loader, &error);
1007 g_error_free (error);
1008 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1010 g_object_ref (pixbuf);
1011 g_object_unref (loader);
1016 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1017 GdkPixbuf *new_pixbuf;
1019 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1020 gdk_pixbuf_get_width (pixbuf);
1021 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1022 g_object_unref (pixbuf);
1023 pixbuf = new_pixbuf;
1027 *stream_size = size;
1033 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1035 ModestMsgEditWindowPrivate *priv;
1038 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1040 for (iter = tny_list_create_iterator (attachments);
1041 !tny_iterator_is_done (iter);
1042 tny_iterator_next (iter)) {
1043 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1044 const gchar *cid = tny_mime_part_get_content_id (part);
1045 const gchar *mime_type = tny_mime_part_get_content_type (part);
1046 if ((cid != NULL)&&(mime_type != NULL)) {
1047 guint64 stream_size;
1048 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1049 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1052 g_object_unref (stream);
1054 if (pixbuf != NULL) {
1055 priv->images_count ++;
1056 priv->images_size += stream_size;
1057 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1058 g_object_unref (pixbuf);
1061 g_object_unref (part);
1063 g_object_unref (iter);
1067 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1069 TnyMimePart *parent = NULL;
1070 const gchar *content_type = NULL;
1071 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1073 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1075 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1076 parent = g_object_ref (msg);
1077 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1078 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1081 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1082 iter = tny_list_create_iterator (parts);
1083 while (!tny_iterator_is_done (iter)) {
1085 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1086 content_type = tny_mime_part_get_content_type (part);
1087 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1091 g_object_unref (part);
1093 tny_iterator_next (iter);
1095 g_object_unref (iter);
1096 g_object_unref (parts);
1099 if (parent != NULL) {
1100 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1103 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1104 iter = tny_list_create_iterator (parts);
1105 while (!tny_iterator_is_done (iter)) {
1107 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1108 content_type = tny_mime_part_get_content_type (part);
1109 if (content_type && g_str_has_prefix (content_type, "image/")) {
1110 tny_list_prepend (priv->images, (GObject *) part);
1112 g_object_unref (part);
1113 tny_iterator_next (iter);
1115 g_object_unref (iter);
1116 g_object_unref (parts);
1117 g_object_unref (parent);
1122 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1125 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1127 for (iter = tny_list_create_iterator (attachments) ;
1128 !tny_iterator_is_done (iter);
1129 tny_iterator_next (iter)) {
1130 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1131 const gchar *cid = tny_mime_part_get_content_id (part);
1133 char *invalid = NULL;
1134 gint int_cid = strtol (cid, &invalid, 10);
1135 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1136 priv->next_cid = int_cid + 1;
1139 g_object_unref (part);
1141 g_object_unref (iter);
1145 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1148 gchar *to, *cc, *bcc, *subject;
1150 ModestMsgEditWindowPrivate *priv;
1151 ModestWindowPrivate *parent_priv;
1153 TnyHeaderFlags priority_flags;
1154 TnyFolder *msg_folder;
1155 gboolean is_html = FALSE;
1156 gboolean field_view_set;
1158 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1159 g_return_if_fail (TNY_IS_MSG (msg));
1161 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1162 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1164 header = tny_msg_get_header (msg);
1165 to = tny_header_dup_to (header);
1166 cc = tny_header_dup_cc (header);
1167 bcc = tny_header_dup_bcc (header);
1168 subject = tny_header_dup_subject (header);
1169 priority_flags = tny_header_get_priority (header);
1172 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1174 field_view_set = TRUE;
1176 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1177 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1178 gtk_widget_show (priv->cc_caption);
1179 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1180 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1181 gtk_widget_hide (priv->cc_caption);
1182 field_view_set = FALSE;
1184 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1186 field_view_set = TRUE;
1188 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1189 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1190 gtk_widget_show (priv->bcc_caption);
1191 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1192 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1193 gtk_widget_hide (priv->bcc_caption);
1194 field_view_set = FALSE;
1196 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1200 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1201 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1204 update_window_title (self);
1206 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1207 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1209 if ((body == NULL)||(body[0] == '\0')) {
1211 body = modest_text_utils_convert_to_html ("");
1214 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1215 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1218 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1221 /* Add attachments to the view */
1222 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1223 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1224 if (tny_list_get_length (priv->attachments) == 0) {
1225 gtk_widget_hide (priv->attachments_caption);
1227 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1228 gtk_widget_show_all (priv->attachments_caption);
1230 get_related_images (self, msg);
1231 update_next_cid (self, priv->attachments);
1232 update_next_cid (self, priv->images);
1233 replace_with_images (self, priv->images);
1235 if (preserve_is_rich && !is_html) {
1236 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1237 /* Get the default format required from configuration */
1238 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1239 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1242 /* Set the default focus depending on having already a To: field or not */
1243 if ((!to)||(*to == '\0')) {
1244 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1246 gtk_widget_grab_focus (priv->msg_body);
1249 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1251 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1252 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1254 modest_msg_edit_window_set_modified (self, FALSE);
1256 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1257 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1258 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1259 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1261 if (priv->msg_uid) {
1262 g_free (priv->msg_uid);
1263 priv->msg_uid = NULL;
1266 /* we should set a reference to the incoming message if it is a draft */
1267 msg_folder = tny_msg_get_folder (msg);
1269 if (modest_tny_folder_is_local_folder (msg_folder)) {
1270 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1271 if (type == TNY_FOLDER_TYPE_INVALID)
1272 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1274 if (type == TNY_FOLDER_TYPE_DRAFTS)
1275 priv->draft_msg = g_object_ref(msg);
1276 if (type == TNY_FOLDER_TYPE_OUTBOX)
1277 priv->outbox_msg = g_object_ref(msg);
1278 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1280 g_object_unref (msg_folder);
1291 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1293 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1294 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1295 GtkWidget *placeholder;
1296 GtkWidget *tool_item;
1301 GtkWidget *sizes_menu;
1302 GtkWidget *fonts_menu;
1306 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1307 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1308 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1309 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1311 /* Font color placeholder */
1312 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1313 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1316 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1317 priv->font_color_button = hildon_color_button_new ();
1318 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1319 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1320 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1321 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1322 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1323 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1324 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1325 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1327 G_CALLBACK (modest_msg_edit_window_color_button_change),
1330 /* Font size and face placeholder */
1331 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1332 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1334 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1335 priv->size_tool_button_label = gtk_label_new (NULL);
1336 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1337 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1338 size_text, "</span>", NULL);
1339 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1341 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1342 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1343 sizes_menu = gtk_menu_new ();
1344 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1345 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1348 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1349 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1351 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1355 if (wp_font_size[size_index] == 12)
1356 priv->current_size_index = size_index;
1360 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1361 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1362 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1363 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1364 priv->font_size_toolitem = tool_item;
1367 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1368 priv->font_tool_button_label = gtk_label_new (NULL);
1369 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1370 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1372 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1373 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1374 fonts_menu = gtk_menu_new ();
1375 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1376 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1379 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1381 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1382 0, wp_get_font_name (font_index),
1385 if (font_index == DEFAULT_FONT)
1386 priv->current_face_index = font_index;
1388 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1389 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1390 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1391 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1392 priv->font_face_toolitem = tool_item;
1394 /* Set expand and homogeneous for remaining items */
1395 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1396 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1397 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1398 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1399 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1400 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1401 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1402 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1403 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1405 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1406 will not show the tool items added to the placeholders) */
1407 gtk_widget_show_all (parent_priv->toolbar);
1409 /* Set the no show all *after* showing all items. We do not
1410 want the toolbar to be shown with a show all because it
1411 could go agains the gconf setting regarding showing or not
1412 the toolbar of the editor window */
1413 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1419 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1422 ModestWindowPrivate *parent_priv;
1423 ModestMsgEditWindowPrivate *priv;
1424 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1425 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1426 ModestWindowMgr *mgr = NULL;
1428 g_return_val_if_fail (msg, NULL);
1429 g_return_val_if_fail (account_name, NULL);
1431 mgr = modest_runtime_get_window_mgr ();
1433 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1435 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1436 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1438 /* Menubar. Update the state of some toggles */
1439 priv->from_field_protos = get_transports ();
1440 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1441 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1442 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1443 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1445 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1446 hildon_touch_selector_get_current_text
1447 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1448 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1449 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1452 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1454 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1456 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1458 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1460 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1461 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1462 /* Add common dimming rules */
1463 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1464 modest_msg_edit_window_toolbar_dimming_entries,
1465 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1466 MODEST_WINDOW (obj));
1467 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1468 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1469 MODEST_WINDOW (obj));
1470 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1471 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1472 MODEST_WINDOW (obj));
1473 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1474 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1475 MODEST_WINDOW (obj));
1476 /* Insert dimming rules group for this window */
1477 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1478 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1480 /* Setup app menu */
1481 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1483 /* Checks the dimming rules */
1484 g_object_unref (toolbar_rules_group);
1485 g_object_unref (clipboard_rules_group);
1486 gtk_widget_hide (priv->priority_icon);
1487 gtk_widget_queue_resize (priv->subject_box);
1488 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1490 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1492 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1493 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1494 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1495 priv->update_caption_visibility = TRUE;
1497 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1499 /* Track account-removed signal, this window should be closed
1500 in the case we're creating a mail associated to the account
1502 priv->account_removed_handler_id =
1503 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1505 G_CALLBACK(on_account_removed),
1508 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1510 return (ModestWindow*) obj;
1514 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1516 GString **string_buffer = (GString **) user_data;
1518 *string_buffer = g_string_append (*string_buffer, buffer);
1524 * @result: A new string which should be freed with g_free().
1527 get_formatted_data (ModestMsgEditWindow *edit_window)
1529 ModestMsgEditWindowPrivate *priv;
1530 GString *string_buffer = g_string_new ("");
1532 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1534 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1536 modest_text_utils_hyperlinkify (string_buffer);
1538 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1540 return g_string_free (string_buffer, FALSE);
1545 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1548 const gchar *account_name;
1549 ModestMsgEditWindowPrivate *priv;
1550 TnyIterator *att_iter;
1552 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1554 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1556 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1557 g_return_val_if_fail (account_name, NULL);
1560 /* don't free these (except from) */
1561 data = g_slice_new0 (MsgData);
1562 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1564 data->account_name = g_strdup (account_name);
1565 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1566 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1567 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1568 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1569 if (priv->draft_msg) {
1570 data->draft_msg = g_object_ref (priv->draft_msg);
1571 } else if (priv->outbox_msg) {
1572 data->draft_msg = g_object_ref (priv->outbox_msg);
1574 data->draft_msg = NULL;
1577 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1579 gtk_text_buffer_get_bounds (buf, &b, &e);
1580 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1582 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1583 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1585 data->html_body = NULL;
1587 /* deep-copy the data */
1588 att_iter = tny_list_create_iterator (priv->attachments);
1589 data->attachments = NULL;
1590 while (!tny_iterator_is_done (att_iter)) {
1591 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1592 if (!(TNY_IS_MIME_PART(part))) {
1593 g_warning ("strange data in attachment list");
1594 g_object_unref (part);
1595 tny_iterator_next (att_iter);
1598 data->attachments = g_list_append (data->attachments,
1600 tny_iterator_next (att_iter);
1602 g_object_unref (att_iter);
1604 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1605 att_iter = tny_list_create_iterator (priv->images);
1606 data->images = NULL;
1607 while (!tny_iterator_is_done (att_iter)) {
1608 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1610 if (!(TNY_IS_MIME_PART(part))) {
1611 g_warning ("strange data in attachment list");
1612 g_object_unref (part);
1613 tny_iterator_next (att_iter);
1616 cid = tny_mime_part_get_content_id (part);
1618 gchar *image_tag_id;
1619 GtkTextTag *image_tag;
1621 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1622 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1623 g_free (image_tag_id);
1625 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1627 ((gtk_text_iter_has_tag (&iter, image_tag))||
1628 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1629 data->images = g_list_append (data->images,
1630 g_object_ref (part));
1632 g_object_unref (part);
1633 tny_iterator_next (att_iter);
1635 g_object_unref (att_iter);
1637 data->priority_flags = priv->priority_flags;
1644 unref_gobject (GObject *obj, gpointer data)
1646 if (!G_IS_OBJECT(obj))
1648 g_object_unref (obj);
1652 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1655 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1663 g_free (data->from);
1664 g_free (data->subject);
1665 g_free (data->plain_body);
1666 g_free (data->html_body);
1667 g_free (data->account_name);
1669 if (data->draft_msg != NULL) {
1670 g_object_unref (data->draft_msg);
1671 data->draft_msg = NULL;
1674 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1675 g_list_free (data->attachments);
1676 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1677 g_list_free (data->images);
1679 g_slice_free (MsgData, data);
1683 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1685 guint64 *parts_size)
1687 ModestMsgEditWindowPrivate *priv;
1689 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1691 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1693 /* TODO: add images */
1694 *parts_size += priv->images_size;
1695 *parts_count += priv->images_count;
1700 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1703 ModestMsgEditWindowPrivate *priv = NULL;
1704 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1706 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1708 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1710 return MODEST_MSG_EDIT_FORMAT_HTML;
1712 return MODEST_MSG_EDIT_FORMAT_TEXT;
1716 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1717 ModestMsgEditFormat format)
1719 ModestMsgEditWindowPrivate *priv;
1721 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1722 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1725 case MODEST_MSG_EDIT_FORMAT_HTML:
1726 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1728 case MODEST_MSG_EDIT_FORMAT_TEXT:
1729 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1732 g_return_if_reached ();
1736 ModestMsgEditFormatState *
1737 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1739 ModestMsgEditFormatState *format_state = NULL;
1740 ModestMsgEditWindowPrivate *priv;
1741 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1743 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1744 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1746 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1748 format_state = g_new0 (ModestMsgEditFormatState, 1);
1749 format_state->bold = buffer_format->bold&0x1;
1750 format_state->italics = buffer_format->italic&0x1;
1751 format_state->bullet = buffer_format->bullet&0x1;
1752 format_state->color = buffer_format->color;
1753 format_state->font_size = buffer_format->font_size;
1754 format_state->font_family = wp_get_font_name (buffer_format->font);
1755 format_state->justification = buffer_format->justification;
1756 g_free (buffer_format);
1758 return format_state;
1763 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1764 const ModestMsgEditFormatState *format_state)
1766 ModestMsgEditWindowPrivate *priv;
1767 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1768 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1769 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1770 g_return_if_fail (format_state != NULL);
1772 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1773 gtk_widget_grab_focus (priv->msg_body);
1774 buffer_format->bold = (format_state->bold != FALSE);
1775 buffer_format->italic = (format_state->italics != FALSE);
1776 buffer_format->color = format_state->color;
1777 buffer_format->font_size = format_state->font_size;
1778 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1779 buffer_format->justification = format_state->justification;
1780 buffer_format->bullet = format_state->bullet;
1782 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1784 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1785 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1786 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1787 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1788 buffer_format->cs.font = (buffer_format->font != current_format->font);
1789 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1790 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1792 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1793 if (buffer_format->cs.bold) {
1794 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1795 GINT_TO_POINTER (buffer_format->bold&0x1));
1797 if (buffer_format->cs.italic) {
1798 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1799 GINT_TO_POINTER (buffer_format->italic&0x1));
1801 if (buffer_format->cs.color) {
1802 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1803 GINT_TO_POINTER (&(buffer_format->color)));
1805 if (buffer_format->cs.font_size) {
1806 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1807 GINT_TO_POINTER (buffer_format->font_size));
1809 if (buffer_format->cs.justification) {
1810 switch (buffer_format->justification) {
1811 case GTK_JUSTIFY_LEFT:
1812 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1813 GINT_TO_POINTER(TRUE));
1815 case GTK_JUSTIFY_CENTER:
1816 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1817 GINT_TO_POINTER(TRUE));
1819 case GTK_JUSTIFY_RIGHT:
1820 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1821 GINT_TO_POINTER(TRUE));
1828 if (buffer_format->cs.font) {
1829 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1830 GINT_TO_POINTER (buffer_format->font));
1832 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1833 if (buffer_format->cs.bullet) {
1834 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1835 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1837 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1839 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1841 g_free (buffer_format);
1842 g_free (current_format);
1844 /* Check dimming rules */
1845 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1846 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1850 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1852 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1854 ModestWindowPrivate *parent_priv;
1855 ModestMsgEditWindowPrivate *priv;
1857 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1858 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1860 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1861 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1862 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1863 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1865 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1866 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1867 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1870 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1872 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1873 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1875 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1876 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1878 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1879 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1882 switch (buffer_format->justification)
1884 case GTK_JUSTIFY_LEFT:
1885 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1887 case GTK_JUSTIFY_CENTER:
1888 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1890 case GTK_JUSTIFY_RIGHT:
1891 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1898 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1900 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1901 G_CALLBACK (modest_msg_edit_window_color_button_change),
1903 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1904 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1905 G_CALLBACK (modest_msg_edit_window_color_button_change),
1908 if (priv->current_size_index != buffer_format->font_size) {
1912 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
1913 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
1917 priv->current_size_index = buffer_format->font_size;
1919 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
1920 markup = g_strconcat ("<span font_family='Sans'>",
1921 size_text, "</span>", NULL);
1923 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1927 gtk_tree_path_free (path);
1930 if (priv->current_face_index != buffer_format->font) {
1934 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
1935 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
1939 priv->current_face_index = buffer_format->font;
1940 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
1941 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
1942 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1949 g_free (buffer_format);
1953 #ifdef MODEST_HILDON_VERSION_0
1955 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1958 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1959 ModestMsgEditWindowPrivate *priv;
1960 GtkWidget *dialog = NULL;
1962 GdkColor *new_color = NULL;
1964 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1965 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1967 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1968 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1969 g_free (buffer_format);
1971 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
1972 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1973 if (new_color != NULL) {
1974 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1975 (gpointer) new_color);
1978 gtk_widget_destroy (dialog);
1983 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1986 ModestMsgEditWindowPrivate *priv;
1987 GtkWidget *dialog = NULL;
1989 GdkColor *old_color = NULL;
1990 const GdkColor *new_color = NULL;
1992 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1993 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1995 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1996 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1998 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
1999 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2000 if (new_color != NULL)
2001 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2003 gtk_widget_destroy (dialog);
2009 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2012 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2013 ModestMsgEditWindowPrivate *priv;
2014 GtkWidget *dialog = NULL;
2016 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2017 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2019 dialog = hildon_color_chooser_new ();
2020 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2021 g_free (buffer_format);
2023 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2025 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2026 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2029 gtk_widget_destroy (dialog);
2034 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2037 ModestMsgEditWindowPrivate *priv;
2038 GtkWidget *dialog = NULL;
2039 GdkColor *old_color = NULL;
2041 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2042 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2044 dialog = hildon_color_chooser_new ();
2045 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2047 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2049 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2050 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2052 gtk_widget_destroy (dialog);
2055 #endif /*!MODEST_HILDON_VERSION_0*/
2060 create_stream_for_uri (const gchar* uri)
2065 TnyStream *result = NULL;
2067 GnomeVFSHandle *handle = NULL;
2068 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2069 if (test == GNOME_VFS_OK) {
2070 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2071 /* Streams over OBEX (Bluetooth) are not seekable but
2072 * we expect them to be (we might need to read them
2073 * several times). So if this is a Bluetooth URI just
2074 * read the whole file into memory (this is not a fast
2075 * protocol so we can assume that these files are not
2076 * going to be very big) */
2077 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2078 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2079 TnyStream *memstream = tny_camel_mem_stream_new ();
2080 tny_stream_write_to_stream (vfssstream, memstream);
2081 g_object_unref (vfssstream);
2084 result = vfssstream;
2092 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2095 ModestMsgEditWindowPrivate *priv;
2096 GtkWidget *dialog = NULL;
2098 GSList *uris = NULL;
2099 GSList *uri_node = NULL;
2101 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2103 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2104 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2105 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2107 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2109 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2110 GTK_WINDOW (dialog), GTK_WINDOW (window));
2112 response = gtk_dialog_run (GTK_DIALOG (dialog));
2114 case GTK_RESPONSE_OK:
2115 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2120 gtk_widget_destroy (dialog);
2122 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2124 GnomeVFSHandle *handle = NULL;
2125 GnomeVFSResult result;
2126 GtkTextIter position;
2127 GtkTextMark *insert_mark;
2129 uri = (const gchar *) uri_node->data;
2130 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2131 if (result == GNOME_VFS_OK) {
2133 GnomeVFSFileInfo *info;
2134 gchar *filename, *basename, *escaped_filename;
2135 TnyMimePart *mime_part;
2137 const gchar *mime_type = NULL;
2138 GnomeVFSURI *vfs_uri;
2139 guint64 stream_size;
2141 gnome_vfs_close (handle);
2142 vfs_uri = gnome_vfs_uri_new (uri);
2144 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2145 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2146 g_free (escaped_filename);
2147 gnome_vfs_uri_unref (vfs_uri);
2148 info = gnome_vfs_file_info_new ();
2150 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2151 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2153 mime_type = gnome_vfs_file_info_get_mime_type (info);
2155 mime_part = tny_platform_factory_new_mime_part
2156 (modest_runtime_get_platform_factory ());
2158 TnyStream *stream = create_stream_for_uri (uri);
2160 if (stream == NULL) {
2162 modest_platform_information_banner (NULL, NULL,
2163 _FM("sfil_ib_opening_not_allowed"));
2165 g_object_unref (mime_part);
2166 gnome_vfs_file_info_unref (info);
2170 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2172 content_id = g_strdup_printf ("%d", priv->next_cid);
2173 tny_mime_part_set_content_id (mime_part, content_id);
2174 g_free (content_id);
2177 basename = g_path_get_basename (filename);
2178 tny_mime_part_set_filename (mime_part, basename);
2181 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2183 if (pixbuf != NULL) {
2184 priv->images_size += stream_size;
2185 priv->images_count ++;
2186 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2187 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2188 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2189 g_object_unref (pixbuf);
2192 tny_list_prepend (priv->images, (GObject *) mime_part);
2193 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2195 g_object_unref (mime_part);
2196 gnome_vfs_file_info_unref (info);
2205 on_attach_file_response (GtkDialog *dialog,
2209 GSList *uris = NULL;
2211 GnomeVFSFileSize total_size, allowed_size;
2212 ModestMsgEditWindow *window;
2213 ModestMsgEditWindowPrivate *priv;
2218 case GTK_RESPONSE_OK:
2219 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2225 window = MODEST_MSG_EDIT_WINDOW (user_data);
2226 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2228 /* allowed size is the maximum size - what's already there */
2229 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2230 &att_num, &att_size);
2231 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2234 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2236 const gchar *uri = (const gchar *) uri_node->data;
2239 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2241 if (total_size > allowed_size) {
2242 g_warning ("%s: total size: %u",
2243 __FUNCTION__, (unsigned int)total_size);
2246 allowed_size -= total_size;
2248 g_slist_foreach (uris, (GFunc) g_free, NULL);
2249 g_slist_free (uris);
2251 gtk_widget_destroy (GTK_WIDGET (dialog));
2255 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2257 GtkWidget *dialog = NULL;
2258 ModestMsgEditWindowPrivate *priv;
2260 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2262 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2264 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2267 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2268 GTK_FILE_CHOOSER_ACTION_OPEN);
2269 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2270 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2271 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2272 GTK_WINDOW (dialog), GTK_WINDOW (window));
2274 /* Connect to response & show */
2275 g_signal_connect (dialog, "response",
2276 G_CALLBACK (on_attach_file_response), window);
2277 gtk_widget_show (dialog);
2282 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2284 GnomeVFSFileSize allowed_size)
2287 GnomeVFSHandle *handle = NULL;
2288 ModestMsgEditWindowPrivate *priv;
2289 GnomeVFSResult result;
2290 GnomeVFSFileSize size = 0;
2291 g_return_val_if_fail (window, 0);
2292 g_return_val_if_fail (uri, 0);
2294 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2296 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2297 if (result == GNOME_VFS_OK) {
2298 TnyMimePart *mime_part;
2300 const gchar *mime_type = NULL;
2302 gchar *escaped_filename;
2305 GnomeVFSFileInfo *info;
2306 GnomeVFSURI *vfs_uri;
2308 gnome_vfs_close (handle);
2309 vfs_uri = gnome_vfs_uri_new (uri);
2312 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2313 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2314 g_free (escaped_filename);
2315 gnome_vfs_uri_unref (vfs_uri);
2317 info = gnome_vfs_file_info_new ();
2319 if (gnome_vfs_get_file_info (uri,
2321 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2323 mime_type = gnome_vfs_file_info_get_mime_type (info);
2324 mime_part = tny_platform_factory_new_mime_part
2325 (modest_runtime_get_platform_factory ());
2327 /* try to get the attachment's size; this may fail for weird
2328 * file systems, like obex, upnp... */
2329 if (allowed_size != 0 &&
2330 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2332 if (size > allowed_size) {
2333 modest_platform_information_banner (NULL, NULL,
2334 _FM("sfil_ib_opening_not_allowed"));
2338 g_warning ("%s: could not get attachment size", __FUNCTION__);
2340 stream = create_stream_for_uri (uri);
2342 if (stream == NULL) {
2344 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2346 g_object_unref (mime_part);
2347 gnome_vfs_file_info_unref (info);
2351 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2352 g_object_unref (stream);
2354 content_id = g_strdup_printf ("%d", priv->next_cid);
2355 tny_mime_part_set_content_id (mime_part, content_id);
2356 g_free (content_id);
2359 basename = g_path_get_basename (filename);
2360 tny_mime_part_set_filename (mime_part, basename);
2363 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2364 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2366 info->size == 0, info->size);
2367 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2368 gtk_widget_show_all (priv->attachments_caption);
2369 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2371 g_object_unref (mime_part);
2372 gnome_vfs_file_info_unref (info);
2379 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2382 ModestMsgEditWindowPrivate *priv;
2385 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2386 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2388 if (att_list == NULL) {
2389 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2390 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2391 g_object_unref (att_list);
2396 g_object_ref (att_list);
2399 if (tny_list_get_length (att_list) == 0) {
2400 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2402 gboolean dialog_response;
2403 gchar *message = NULL;
2404 gchar *filename = NULL;
2406 if (tny_list_get_length (att_list) == 1) {
2408 iter = tny_list_create_iterator (att_list);
2409 part = (TnyMimePart *) tny_iterator_get_current (iter);
2410 g_object_unref (iter);
2411 if (TNY_IS_MSG (part)) {
2412 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2414 filename = tny_header_dup_subject (header);
2415 g_object_unref (header);
2417 if (filename == NULL) {
2418 filename = g_strdup (_("mail_va_no_subject"));
2421 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2423 g_object_unref (part);
2425 filename = g_strdup ("");
2427 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2428 "emev_nc_delete_attachments",
2429 tny_list_get_length (att_list)), filename);
2432 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2436 if (dialog_response != GTK_RESPONSE_OK) {
2437 g_object_unref (att_list);
2441 for (iter = tny_list_create_iterator (att_list);
2442 !tny_iterator_is_done (iter);
2443 tny_iterator_next (iter)) {
2444 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2445 const gchar *att_id;
2446 tny_list_remove (priv->attachments, (GObject *) mime_part);
2448 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2450 if (tny_list_get_length (priv->attachments) == 0)
2451 gtk_widget_hide (priv->attachments_caption);
2452 att_id = tny_mime_part_get_content_id (mime_part);
2454 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2456 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2457 g_object_unref (mime_part);
2459 g_object_unref (iter);
2462 g_object_unref (att_list);
2464 /* if the last attachment has been removed, focus the Subject: field */
2465 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2466 gtk_widget_grab_focus (priv->subject_field);
2470 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2473 ModestMsgEditWindowPrivate *priv;
2474 GdkColor *new_color;
2475 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2477 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2478 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2481 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2483 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2485 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2487 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2492 font_size_clicked (GtkToolButton *button,
2493 ModestMsgEditWindow *window)
2495 ModestMsgEditWindowPrivate *priv;
2496 GtkWidget *selector, *dialog;
2498 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2500 selector = hildon_touch_selector_new ();
2501 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2502 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2504 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2505 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2507 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2511 WPTextBufferFormat format;
2513 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2515 memset (&format, 0, sizeof (format));
2516 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2518 format.cs.font_size = TRUE;
2519 format.cs.text_position = TRUE;
2520 format.cs.font = TRUE;
2521 format.font_size = new_index;
2522 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2524 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2525 GINT_TO_POINTER (new_index)))
2526 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2528 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2529 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2530 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2531 size_text, "</span>", NULL);
2533 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2537 gtk_widget_destroy (dialog);
2539 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2544 font_face_clicked (GtkToolButton *button,
2545 ModestMsgEditWindow *window)
2547 ModestMsgEditWindowPrivate *priv;
2548 GtkWidget *selector, *dialog;
2549 GtkCellRenderer *renderer;
2551 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2553 selector = hildon_touch_selector_new ();
2554 renderer = gtk_cell_renderer_text_new ();
2555 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2556 renderer, "family", 0, "text", 0, NULL);
2557 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2559 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2560 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2562 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2563 gint new_font_index;
2567 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2568 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2569 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2573 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2575 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2576 GINT_TO_POINTER(new_font_index)))
2577 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2579 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2580 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2582 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2586 gtk_tree_path_free (path);
2589 gtk_widget_destroy (dialog);
2591 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2596 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2599 ModestMsgEditWindowPrivate *priv = NULL;
2600 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2602 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2603 if (!priv->update_caption_visibility)
2606 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2608 gtk_widget_show (priv->cc_caption);
2610 gtk_widget_hide (priv->cc_caption);
2612 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2616 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2619 ModestMsgEditWindowPrivate *priv = NULL;
2620 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2622 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2623 if (!priv->update_caption_visibility)
2626 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2628 gtk_widget_show (priv->bcc_caption);
2630 gtk_widget_hide (priv->bcc_caption);
2632 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2636 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2637 ModestRecptEditor *editor)
2639 ModestMsgEditWindowPrivate *priv;
2641 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2642 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2644 /* we check for low-mem; in that case, show a warning, and don't allow
2645 * for the addressbook
2647 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2650 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2652 if (editor == NULL) {
2653 GtkWidget *view_focus;
2654 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2656 /* This code should be kept in sync with ModestRecptEditor. The
2657 textview inside the recpt editor is the one that really gets the
2658 focus. As it's inside a scrolled window, and this one inside the
2659 hbox recpt editor inherits from, we'll need to go up in the
2660 hierarchy to know if the text view is part of the recpt editor
2661 or if it's a different text entry */
2663 if (gtk_widget_get_parent (view_focus)) {
2664 GtkWidget *first_parent;
2666 first_parent = gtk_widget_get_parent (view_focus);
2667 if (gtk_widget_get_parent (first_parent) &&
2668 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2669 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2674 editor = MODEST_RECPT_EDITOR (priv->to_field);
2678 modest_address_book_select_addresses (editor);
2683 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2685 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2687 modest_msg_edit_window_open_addressbook (window, NULL);
2691 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2692 gboolean show_toolbar)
2694 ModestWindowPrivate *parent_priv;
2696 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2697 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2699 /* We can not just use the code of
2700 modest_msg_edit_window_setup_toolbar because it has a
2701 mixture of both initialization and creation code. */
2703 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2705 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2709 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2710 TnyHeaderFlags priority_flags)
2712 ModestMsgEditWindowPrivate *priv;
2713 ModestWindowPrivate *parent_priv;
2715 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2717 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2718 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2720 if (priv->priority_flags != priority_flags) {
2721 GtkAction *priority_action = NULL;
2723 priv->priority_flags = priority_flags;
2725 switch (priority_flags) {
2726 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2727 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2728 MODEST_HEADER_ICON_HIGH,
2729 HILDON_ICON_SIZE_SMALL);
2730 gtk_widget_show (priv->priority_icon);
2731 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2732 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2734 case TNY_HEADER_FLAG_LOW_PRIORITY:
2735 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2736 MODEST_HEADER_ICON_LOW,
2737 HILDON_ICON_SIZE_SMALL);
2738 gtk_widget_show (priv->priority_icon);
2739 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2740 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2743 gtk_widget_hide (priv->priority_icon);
2744 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2745 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2748 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2749 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2751 gtk_widget_queue_resize (priv->subject_box);
2755 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2758 ModestMsgEditWindowPrivate *priv;
2759 ModestWindowPrivate *parent_priv;
2760 gint current_format;
2762 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2764 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2765 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2767 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2768 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2770 if (current_format != file_format) {
2771 switch (file_format) {
2772 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2773 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2774 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2776 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2780 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2781 response = gtk_dialog_run (GTK_DIALOG (dialog));
2782 gtk_widget_destroy (dialog);
2783 if (response == GTK_RESPONSE_OK) {
2784 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2786 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2787 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2792 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2793 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2794 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2799 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2802 ModestMsgEditWindowPrivate *priv;
2803 WPTextBufferFormat oldfmt, fmt;
2804 gint old_position = 0;
2808 GdkColor *color = NULL;
2809 gboolean bold, bold_set, italic, italic_set;
2810 gboolean underline, underline_set;
2811 gboolean strikethrough, strikethrough_set;
2812 gboolean position_set;
2813 gboolean font_size_set, font_set, color_set;
2816 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2817 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2819 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2820 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2821 GTK_WINDOW(dialog), GTK_WINDOW (window));
2823 /* First we get the currently selected font information */
2824 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2826 switch (oldfmt.text_position) {
2827 case TEXT_POSITION_NORMAL:
2830 case TEXT_POSITION_SUPERSCRIPT:
2838 g_object_set (G_OBJECT (dialog),
2839 "bold", oldfmt.bold != FALSE,
2840 "bold-set", !oldfmt.cs.bold,
2841 "underline", oldfmt.underline != FALSE,
2842 "underline-set", !oldfmt.cs.underline,
2843 "italic", oldfmt.italic != FALSE,
2844 "italic-set", !oldfmt.cs.italic,
2845 "strikethrough", oldfmt.strikethrough != FALSE,
2846 "strikethrough-set", !oldfmt.cs.strikethrough,
2847 "color", &oldfmt.color,
2848 "color-set", !oldfmt.cs.color,
2849 "size", wp_font_size[oldfmt.font_size],
2850 "size-set", !oldfmt.cs.font_size,
2851 "position", old_position,
2852 "position-set", !oldfmt.cs.text_position,
2853 "family", wp_get_font_name (oldfmt.font),
2854 "family-set", !oldfmt.cs.font,
2857 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2858 GTK_WINDOW (dialog), GTK_WINDOW (window));
2859 gtk_widget_show_all (dialog);
2860 priv->font_dialog = dialog;
2861 response = gtk_dialog_run (GTK_DIALOG (dialog));
2862 priv->font_dialog = NULL;
2863 if (response == GTK_RESPONSE_OK) {
2865 g_object_get( dialog,
2867 "bold-set", &bold_set,
2868 "underline", &underline,
2869 "underline-set", &underline_set,
2871 "italic-set", &italic_set,
2872 "strikethrough", &strikethrough,
2873 "strikethrough-set", &strikethrough_set,
2875 "color-set", &color_set,
2877 "size-set", &font_size_set,
2878 "family", &font_name,
2879 "family-set", &font_set,
2880 "position", &position,
2881 "position-set", &position_set,
2886 if (response == GTK_RESPONSE_OK) {
2887 memset(&fmt, 0, sizeof(fmt));
2893 fmt.italic = italic;
2894 fmt.cs.italic = TRUE;
2896 if (underline_set) {
2897 fmt.underline = underline;
2898 fmt.cs.underline = TRUE;
2900 if (strikethrough_set) {
2901 fmt.strikethrough = strikethrough;
2902 fmt.cs.strikethrough = TRUE;
2907 ? TEXT_POSITION_NORMAL
2908 : ( ( position == 1 )
2909 ? TEXT_POSITION_SUPERSCRIPT
2910 : TEXT_POSITION_SUBSCRIPT );
2911 fmt.cs.text_position = TRUE;
2912 fmt.font_size = oldfmt.font_size;
2916 fmt.cs.color = TRUE;
2919 fmt.font = wp_get_font_index(font_name,
2924 if (font_size_set) {
2925 fmt.cs.font_size = TRUE;
2926 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2928 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2929 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2931 gtk_widget_destroy (dialog);
2933 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2937 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2939 ModestMsgEditWindowPrivate *priv;
2941 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2942 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2944 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2946 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2947 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2951 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2953 ModestMsgEditWindowPrivate *priv;
2955 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2956 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2958 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2960 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2961 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2966 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2968 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2970 priv->can_undo = can_undo;
2974 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2976 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2978 priv->can_redo = can_redo;
2982 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2984 ModestMsgEditWindowPrivate *priv;
2985 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2986 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2988 return priv->can_undo;
2992 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2994 ModestMsgEditWindowPrivate *priv;
2995 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2996 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2998 return priv->can_redo;
3003 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3006 GtkTextIter match_start, match_end;
3008 if (image_id == NULL)
3011 gtk_text_buffer_get_start_iter (buffer, &iter);
3013 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3014 GSList *tags = gtk_text_iter_get_tags (&match_start);
3016 for (node = tags; node != NULL; node = g_slist_next (node)) {
3017 GtkTextTag *tag = (GtkTextTag *) node->data;
3018 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3019 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3020 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3022 offset = gtk_text_iter_get_offset (&match_start);
3023 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3024 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3028 gtk_text_iter_forward_char (&iter);
3033 message_is_empty (ModestMsgEditWindow *window)
3035 ModestMsgEditWindowPrivate *priv = NULL;
3037 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3038 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3040 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3041 * so we can ignore markup.
3043 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3046 count = gtk_text_buffer_get_char_count (buf);
3052 msg_body_focus (GtkWidget *focus,
3053 GdkEventFocus *event,
3057 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3058 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3059 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3064 recpt_field_changed (GtkTextBuffer *buffer,
3065 ModestMsgEditWindow *editor)
3067 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3068 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3072 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3074 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3075 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3079 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3082 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3083 GtkTextBuffer *buffer;
3085 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3086 gtk_text_buffer_set_modified (buffer, modified);
3087 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3088 gtk_text_buffer_set_modified (buffer, modified);
3089 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3090 gtk_text_buffer_set_modified (buffer, modified);
3091 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3095 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3097 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3098 const char *account_name;
3099 GtkTextBuffer *buffer;
3101 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3102 if (gtk_text_buffer_get_modified (buffer))
3104 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3105 if (gtk_text_buffer_get_modified (buffer))
3107 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3108 if (gtk_text_buffer_get_modified (buffer))
3110 if (gtk_text_buffer_get_modified (priv->text_buffer))
3112 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3113 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3124 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3126 ModestMsgEditWindowPrivate *priv = NULL;
3128 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3129 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3131 /* check if there's no recipient added */
3132 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3133 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3134 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3135 /* no recipient contents, then select contacts */
3136 modest_msg_edit_window_open_addressbook (window, NULL);
3140 g_object_ref (window);
3141 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3142 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3143 g_object_unref (window);
3146 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3147 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3148 g_object_unref (window);
3151 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3152 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3153 g_object_unref (window);
3157 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3158 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3159 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3160 g_object_unref (window);
3167 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3168 ModestMsgEditWindow *window)
3170 modest_msg_edit_window_offer_attach_file (window);
3174 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3176 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3178 return priv->clipboard_text;
3182 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3184 ModestMsgEditWindow *window)
3186 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3187 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3189 if (!GTK_WIDGET_VISIBLE (window))
3192 g_object_ref (window);
3193 text = gtk_clipboard_wait_for_text (selection_clipboard);
3195 if (priv->clipboard_text != NULL) {
3196 g_free (priv->clipboard_text);
3198 priv->clipboard_text = text;
3200 if (GTK_WIDGET_VISIBLE (window)) {
3201 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3203 g_object_unref (window);
3206 static gboolean clipboard_owner_change_idle (gpointer userdata)
3208 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3209 ModestMsgEditWindowPrivate *priv;
3211 gdk_threads_enter ();
3212 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3213 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3215 priv->clipboard_owner_idle = 0;
3216 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3217 gdk_threads_leave ();
3223 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3225 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3226 if (priv->clipboard_owner_idle == 0) {
3227 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3232 subject_field_move_cursor (GtkEntry *entry,
3233 GtkMovementStep step,
3238 if (!GTK_WIDGET_VISIBLE (window))
3241 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3245 update_window_title (ModestMsgEditWindow *window)
3247 ModestMsgEditWindowPrivate *priv = NULL;
3248 const gchar *subject;
3250 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3251 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3252 if (subject == NULL || subject[0] == '\0')
3253 subject = _("mail_va_new_email");
3255 gtk_window_set_title (GTK_WINDOW (window), subject);
3260 subject_field_changed (GtkEditable *editable,
3261 ModestMsgEditWindow *window)
3263 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3264 update_window_title (window);
3265 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3266 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3267 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3271 subject_field_insert_text (GtkEditable *editable,
3273 gint new_text_length,
3275 ModestMsgEditWindow *window)
3277 GString *result = g_string_new ("");
3279 gint result_len = 0;
3280 const gchar *entry_text = NULL;
3283 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3284 old_length = g_utf8_strlen (entry_text, -1);
3286 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3287 gunichar c = g_utf8_get_char_validated (current, 8);
3288 /* Invalid unichar, stop */
3294 result = g_string_append_unichar (result, c);
3298 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3299 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3302 /* Prevent endless recursion */
3303 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3304 g_signal_emit_by_name (editable, "insert-text",
3305 (gpointer) result->str, (gpointer) result->len,
3306 (gpointer) position, (gpointer) window);
3307 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3311 if (result_len + old_length > 1000) {
3312 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3313 _CS("ckdg_ib_maximum_characters_reached"));
3315 g_string_free (result, TRUE);
3319 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3322 ModestMsgEditWindowPrivate *priv = NULL;
3324 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3325 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3327 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3330 gtk_widget_show_all (priv->find_toolbar);
3331 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3333 gtk_widget_hide_all (priv->find_toolbar);
3334 gtk_widget_grab_focus (priv->msg_body);
3339 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3341 GtkTextIter *match_start,
3342 GtkTextIter *match_end)
3344 GtkTextIter end_iter;
3345 gchar *str_casefold;
3348 gchar *range_casefold;
3351 gboolean result = FALSE;
3358 gtk_text_iter_forward_to_end (&end_iter);
3360 str_casefold = g_utf8_casefold (str, -1);
3361 str_chars_n = strlen (str);
3363 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3364 range_casefold = g_utf8_casefold (range_text, -1);
3365 range_chars_n = strlen (range_casefold);
3367 if (range_chars_n < str_chars_n) {
3368 g_free (str_casefold);
3369 g_free (range_text);
3370 g_free (range_casefold);
3374 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3375 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3376 if (!g_utf8_collate (range_subtext, str_casefold)) {
3377 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3379 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3380 match_start, match_end, NULL);
3381 g_free (found_text);
3383 g_free (range_subtext);
3387 g_free (str_casefold);
3388 g_free (range_text);
3389 g_free (range_casefold);
3396 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3397 ModestMsgEditWindow *window)
3399 gchar *current_search = NULL;
3400 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3402 GtkTextIter selection_start, selection_end;
3403 GtkTextIter match_start, match_end;
3404 gboolean continue_search = FALSE;
3406 if (message_is_empty (window)) {
3407 g_free (priv->last_search);
3408 priv->last_search = NULL;
3409 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3413 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3414 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3415 g_free (current_search);
3416 g_free (priv->last_search);
3417 priv->last_search = NULL;
3418 /* Information banner about empty search */
3419 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3423 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3424 continue_search = TRUE;
3426 g_free (priv->last_search);
3427 priv->last_search = g_strdup (current_search);
3430 if (continue_search) {
3431 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3432 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3433 &match_start, &match_end);
3435 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3437 GtkTextIter buffer_start;
3438 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3439 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3440 &match_start, &match_end);
3442 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3445 /* Mark as selected the string found in search */
3447 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3448 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3449 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3451 g_free (priv->last_search);
3452 priv->last_search = NULL;
3454 g_free (current_search);
3458 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3460 ModestMsgEditWindowPrivate *priv;
3462 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3467 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3470 ModestMsgEditWindowPrivate *priv;
3472 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3477 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3478 ModestMsgEditWindow *window)
3480 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3484 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3487 ModestMsgEditWindowPrivate *priv;
3488 TnyHeader *header = NULL;
3490 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3491 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3493 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3494 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3496 if (priv->draft_msg != NULL) {
3497 g_object_unref (priv->draft_msg);
3500 if (draft != NULL) {
3501 g_object_ref (draft);
3502 header = tny_msg_get_header (draft);
3503 if (priv->msg_uid) {
3504 g_free (priv->msg_uid);
3505 priv->msg_uid = NULL;
3507 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3508 if (GTK_WIDGET_REALIZED (window)) {
3509 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3510 gtk_widget_destroy (GTK_WIDGET (window));
3516 priv->draft_msg = draft;
3520 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3521 GtkTextIter *start, GtkTextIter *end,
3524 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3525 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3528 if (tag == NULL) return;
3529 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3530 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3531 replace_with_images (window, priv->images);
3536 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3539 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3541 g_return_if_fail (TNY_IS_MIME_PART (part));
3542 tny_list_prepend (priv->attachments, (GObject *) part);
3543 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3544 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3545 gtk_widget_show_all (priv->attachments_caption);
3546 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3550 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3552 ModestMsgEditWindowPrivate *priv;
3554 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3555 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3557 return priv->msg_uid;
3561 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3562 ModestMsgEditWindowWidgetType widget_type)
3564 ModestMsgEditWindowPrivate *priv;
3566 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3567 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3569 switch (widget_type) {
3570 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3571 return priv->msg_body;
3573 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3574 return priv->to_field;
3576 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3577 return priv->cc_field;
3579 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3580 return priv->bcc_field;
3582 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3583 return priv->subject_field;
3585 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3586 return priv->attachments_view;
3594 remove_tags (WPTextBuffer *buffer)
3596 GtkTextIter start, end;
3598 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3599 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3601 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3605 on_account_removed (TnyAccountStore *account_store,
3606 TnyAccount *account,
3609 /* Do nothing if it's a store account, because we use the
3610 transport to send the messages */
3611 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3612 const gchar *parent_acc = NULL;
3613 const gchar *our_acc = NULL;
3615 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3616 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3617 /* Close this window if I'm showing a message of the removed account */
3618 if (strcmp (parent_acc, our_acc) == 0)
3619 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3624 from_field_changed (HildonPickerButton *button,
3625 ModestMsgEditWindow *self)
3627 ModestMsgEditWindowPrivate *priv;
3628 gboolean has_old_signature, has_new_signature;
3630 GtkTextIter match_start, match_end;
3631 ModestAccountMgr *mgr;
3633 gchar *full_signature;
3635 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3637 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3638 mgr = modest_runtime_get_account_mgr ();
3639 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3640 if (has_old_signature) {
3641 full_signature = g_strconcat ("\n--\n", signature, NULL);
3642 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3643 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3645 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3646 &match_start, &match_end, NULL)) {
3649 g_free (full_signature);
3653 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3654 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3655 if (has_new_signature) {
3656 full_signature = g_strconcat ("\n--\n", signature, NULL);
3657 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3658 g_free (full_signature);
3663 typedef struct _MessageSettingsHelper {
3664 ModestMsgEditWindow *window;
3665 GSList *priority_group;
3666 GSList *format_group;
3667 GtkToggleButton *current_priority;
3668 GtkToggleButton *current_format;
3669 } MessageSettingsHelper;
3672 on_priority_toggle (GtkToggleButton *button,
3673 MessageSettingsHelper *helper)
3676 ModestMsgEditWindowPrivate *priv;
3678 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3679 if (gtk_toggle_button_get_active (button)) {
3681 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3682 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3683 if ((node_button != button) &&
3684 gtk_toggle_button_get_active (node_button)) {
3685 gtk_toggle_button_set_active (node_button, FALSE);
3688 helper->current_priority = button;
3690 gboolean found = FALSE;
3691 /* If no one is active, activate it again */
3692 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3693 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3694 if (gtk_toggle_button_get_active (node_button)) {
3700 gtk_toggle_button_set_active (button, TRUE);
3706 on_format_toggle (GtkToggleButton *button,
3707 MessageSettingsHelper *helper)
3710 ModestMsgEditWindowPrivate *priv;
3712 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3713 if (gtk_toggle_button_get_active (button)) {
3715 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3716 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3717 if ((node_button != button) &&
3718 gtk_toggle_button_get_active (node_button)) {
3719 gtk_toggle_button_set_active (node_button, FALSE);
3722 helper->current_format = button;
3724 gboolean found = FALSE;
3725 /* If no one is active, activate it again */
3726 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3727 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3728 if (gtk_toggle_button_get_active (node_button)) {
3734 gtk_toggle_button_set_active (button, TRUE);
3741 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3746 GtkWidget *priority_hbox;
3747 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3748 GtkWidget *captioned;
3749 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3750 GtkWidget *format_hbox;
3751 GtkWidget *html_toggle, *text_toggle;
3752 ModestMsgEditWindowPrivate *priv;
3753 MessageSettingsHelper helper = {0,};
3755 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3756 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3757 helper.window = window;
3758 helper.priority_group = NULL;
3759 helper.format_group = NULL;
3761 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3762 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3764 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3765 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3766 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3767 vbox = gtk_vbox_new (FALSE, 0);
3768 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
3769 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
3770 gtk_container_add (GTK_CONTAINER (align), vbox);
3771 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
3772 gtk_widget_show (align);
3773 gtk_widget_show (vbox);
3775 /* Priority toggles */
3776 priority_hbox = gtk_hbox_new (TRUE, 0);
3777 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3778 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3779 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3780 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3781 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3782 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3783 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3784 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3785 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3786 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3787 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3788 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3789 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3790 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3791 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3792 gtk_widget_show_all (priority_hbox);
3793 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3794 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3795 gtk_widget_show (captioned);
3796 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3798 /* format toggles */
3799 format_hbox = gtk_hbox_new (TRUE, 0);
3800 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3801 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3802 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3803 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3804 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3805 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3806 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3807 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3808 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3809 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3810 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3811 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3812 gtk_widget_show_all (format_hbox);
3813 gtk_widget_show (format_hbox);
3814 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3817 g_object_unref (title_sizegroup);
3818 g_object_unref (value_sizegroup);
3820 /* Set current values */
3821 switch (priv->priority_flags) {
3822 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3823 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3824 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3826 case TNY_HEADER_FLAG_LOW_PRIORITY:
3827 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3828 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3831 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3832 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3836 switch (modest_msg_edit_window_get_format (window)) {
3837 case MODEST_MSG_EDIT_FORMAT_TEXT:
3838 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3839 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3841 case MODEST_MSG_EDIT_FORMAT_HTML:
3843 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3844 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3848 /* Signal connects */
3849 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3850 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3851 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3852 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3853 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3855 /* Save settings if the user clicked on done */
3856 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3857 TnyHeaderFlags flags;
3858 ModestMsgEditFormat old_format, new_format;
3860 /* Set priority flags */
3861 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3862 if (priv->priority_flags != flags)
3863 modest_msg_edit_window_set_priority_flags (window, flags);
3865 /* Set edit format */
3866 old_format = modest_msg_edit_window_get_format (window);
3867 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3868 if (old_format != new_format) {
3869 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3870 modest_msg_edit_window_set_file_format (window, file_format);
3874 gtk_widget_destroy (dialog);
3875 g_slist_free (helper.priority_group);
3879 on_message_settings (GtkAction *action,
3880 ModestMsgEditWindow *window)
3882 modest_msg_edit_window_show_msg_settings_dialog (window);
3886 on_cc_button_toggled (HildonCheckButton *button,
3887 ModestMsgEditWindow *window)
3889 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3891 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3892 hildon_check_button_get_active (button));
3896 on_bcc_button_toggled (HildonCheckButton *button,
3897 ModestMsgEditWindow *window)
3899 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3901 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3902 hildon_check_button_get_active (button));
3906 setup_menu (ModestMsgEditWindow *self)
3908 ModestMsgEditWindowPrivate *priv = NULL;
3910 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3912 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3914 /* Settings menu buttons */
3915 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3916 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3918 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3919 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3920 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3922 priv->cc_button = hildon_check_button_new (0);
3923 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3924 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3926 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3928 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3929 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3930 priv->bcc_button = hildon_check_button_new (0);
3931 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3932 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3934 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3936 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3937 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3939 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3940 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3941 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3942 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3943 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3944 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3945 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3946 APP_MENU_CALLBACK (on_message_settings),
3948 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3949 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),