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;
984 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
986 if (loader == NULL) {
992 tny_stream_reset (TNY_STREAM (stream));
993 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
994 GError *error = NULL;
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)) {
1001 g_error_free (error);
1006 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1008 g_object_ref (pixbuf);
1009 gdk_pixbuf_loader_close (loader, NULL);
1010 g_object_unref (loader);
1015 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1016 GdkPixbuf *new_pixbuf;
1018 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1019 gdk_pixbuf_get_width (pixbuf);
1020 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1021 g_object_unref (pixbuf);
1022 pixbuf = new_pixbuf;
1026 *stream_size = size;
1032 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1034 ModestMsgEditWindowPrivate *priv;
1037 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1039 for (iter = tny_list_create_iterator (attachments);
1040 !tny_iterator_is_done (iter);
1041 tny_iterator_next (iter)) {
1042 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1043 const gchar *cid = tny_mime_part_get_content_id (part);
1044 const gchar *mime_type = tny_mime_part_get_content_type (part);
1045 if ((cid != NULL)&&(mime_type != NULL)) {
1046 guint64 stream_size;
1047 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1048 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1051 g_object_unref (stream);
1053 if (pixbuf != NULL) {
1054 priv->images_count ++;
1055 priv->images_size += stream_size;
1056 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1057 g_object_unref (pixbuf);
1060 g_object_unref (part);
1062 g_object_unref (iter);
1066 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1068 TnyMimePart *parent = NULL;
1069 const gchar *content_type = NULL;
1070 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1072 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1074 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1075 parent = g_object_ref (msg);
1076 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1077 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1080 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1081 iter = tny_list_create_iterator (parts);
1082 while (!tny_iterator_is_done (iter)) {
1084 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1085 content_type = tny_mime_part_get_content_type (part);
1086 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1090 g_object_unref (part);
1092 tny_iterator_next (iter);
1094 g_object_unref (iter);
1095 g_object_unref (parts);
1098 if (parent != NULL) {
1099 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1102 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1103 iter = tny_list_create_iterator (parts);
1104 while (!tny_iterator_is_done (iter)) {
1106 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1107 content_type = tny_mime_part_get_content_type (part);
1108 if (content_type && g_str_has_prefix (content_type, "image/")) {
1109 tny_list_prepend (priv->images, (GObject *) part);
1111 g_object_unref (part);
1112 tny_iterator_next (iter);
1114 g_object_unref (iter);
1115 g_object_unref (parts);
1116 g_object_unref (parent);
1121 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1124 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1126 for (iter = tny_list_create_iterator (attachments) ;
1127 !tny_iterator_is_done (iter);
1128 tny_iterator_next (iter)) {
1129 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1130 const gchar *cid = tny_mime_part_get_content_id (part);
1132 char *invalid = NULL;
1133 gint int_cid = strtol (cid, &invalid, 10);
1134 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1135 priv->next_cid = int_cid + 1;
1138 g_object_unref (part);
1140 g_object_unref (iter);
1144 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1147 gchar *to, *cc, *bcc, *subject;
1149 ModestMsgEditWindowPrivate *priv;
1150 ModestWindowPrivate *parent_priv;
1152 TnyHeaderFlags priority_flags;
1153 TnyFolder *msg_folder;
1154 gboolean is_html = FALSE;
1155 gboolean field_view_set;
1157 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1158 g_return_if_fail (TNY_IS_MSG (msg));
1160 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1161 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1163 header = tny_msg_get_header (msg);
1164 to = tny_header_dup_to (header);
1165 cc = tny_header_dup_cc (header);
1166 bcc = tny_header_dup_bcc (header);
1167 subject = tny_header_dup_subject (header);
1168 priority_flags = tny_header_get_priority (header);
1171 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1173 field_view_set = TRUE;
1175 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1176 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1177 gtk_widget_show (priv->cc_caption);
1178 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1179 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1180 gtk_widget_hide (priv->cc_caption);
1181 field_view_set = FALSE;
1183 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1185 field_view_set = TRUE;
1187 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1188 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1189 gtk_widget_show (priv->bcc_caption);
1190 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1191 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1192 gtk_widget_hide (priv->bcc_caption);
1193 field_view_set = FALSE;
1195 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1199 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1200 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1203 update_window_title (self);
1205 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1206 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1208 if ((body == NULL)||(body[0] == '\0')) {
1210 body = modest_text_utils_convert_to_html ("");
1213 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1214 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1217 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1220 /* Add attachments to the view */
1221 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1222 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1223 if (tny_list_get_length (priv->attachments) == 0) {
1224 gtk_widget_hide (priv->attachments_caption);
1226 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1227 gtk_widget_show_all (priv->attachments_caption);
1229 get_related_images (self, msg);
1230 update_next_cid (self, priv->attachments);
1231 update_next_cid (self, priv->images);
1232 replace_with_images (self, priv->images);
1234 if (preserve_is_rich && !is_html) {
1235 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1236 /* Get the default format required from configuration */
1237 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1238 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1241 /* Set the default focus depending on having already a To: field or not */
1242 if ((!to)||(*to == '\0')) {
1243 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1245 gtk_widget_grab_focus (priv->msg_body);
1248 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1250 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1251 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1253 modest_msg_edit_window_set_modified (self, FALSE);
1255 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1256 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1257 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1258 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1260 if (priv->msg_uid) {
1261 g_free (priv->msg_uid);
1262 priv->msg_uid = NULL;
1265 /* we should set a reference to the incoming message if it is a draft */
1266 msg_folder = tny_msg_get_folder (msg);
1268 if (modest_tny_folder_is_local_folder (msg_folder)) {
1269 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1270 if (type == TNY_FOLDER_TYPE_INVALID)
1271 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1273 if (type == TNY_FOLDER_TYPE_DRAFTS)
1274 priv->draft_msg = g_object_ref(msg);
1275 if (type == TNY_FOLDER_TYPE_OUTBOX)
1276 priv->outbox_msg = g_object_ref(msg);
1277 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1279 g_object_unref (msg_folder);
1290 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1292 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1293 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1294 GtkWidget *placeholder;
1295 GtkWidget *tool_item;
1300 GtkWidget *sizes_menu;
1301 GtkWidget *fonts_menu;
1305 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1306 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1307 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1308 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1310 /* Font color placeholder */
1311 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1312 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1315 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1316 priv->font_color_button = hildon_color_button_new ();
1317 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1318 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1319 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1320 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1321 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1322 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1323 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1324 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1326 G_CALLBACK (modest_msg_edit_window_color_button_change),
1329 /* Font size and face placeholder */
1330 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1331 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1333 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1334 priv->size_tool_button_label = gtk_label_new (NULL);
1335 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1336 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1337 size_text, "</span>", NULL);
1338 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1340 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1341 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1342 sizes_menu = gtk_menu_new ();
1343 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1344 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1347 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1348 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1350 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1354 if (wp_font_size[size_index] == 12)
1355 priv->current_size_index = size_index;
1359 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1360 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1361 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1362 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1363 priv->font_size_toolitem = tool_item;
1366 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1367 priv->font_tool_button_label = gtk_label_new (NULL);
1368 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1369 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1371 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1372 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1373 fonts_menu = gtk_menu_new ();
1374 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1375 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1378 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1380 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1381 0, wp_get_font_name (font_index),
1384 if (font_index == DEFAULT_FONT)
1385 priv->current_face_index = font_index;
1387 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1388 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1389 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1390 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1391 priv->font_face_toolitem = tool_item;
1393 /* Set expand and homogeneous for remaining items */
1394 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1395 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1396 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1397 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1398 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1399 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1400 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1401 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1402 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1404 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1405 will not show the tool items added to the placeholders) */
1406 gtk_widget_show_all (parent_priv->toolbar);
1408 /* Set the no show all *after* showing all items. We do not
1409 want the toolbar to be shown with a show all because it
1410 could go agains the gconf setting regarding showing or not
1411 the toolbar of the editor window */
1412 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1418 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1421 ModestWindowPrivate *parent_priv;
1422 ModestMsgEditWindowPrivate *priv;
1423 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1424 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1425 ModestWindowMgr *mgr = NULL;
1427 g_return_val_if_fail (msg, NULL);
1428 g_return_val_if_fail (account_name, NULL);
1430 mgr = modest_runtime_get_window_mgr ();
1432 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1434 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1435 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1437 /* Menubar. Update the state of some toggles */
1438 priv->from_field_protos = get_transports ();
1439 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1440 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1441 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1442 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1444 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1445 hildon_touch_selector_get_current_text
1446 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1447 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1448 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1451 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1453 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1455 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1457 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1459 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1460 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1461 /* Add common dimming rules */
1462 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1463 modest_msg_edit_window_toolbar_dimming_entries,
1464 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1465 MODEST_WINDOW (obj));
1466 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1467 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1468 MODEST_WINDOW (obj));
1469 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1470 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1471 MODEST_WINDOW (obj));
1472 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1473 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1474 MODEST_WINDOW (obj));
1475 /* Insert dimming rules group for this window */
1476 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1477 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1479 /* Setup app menu */
1480 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1482 /* Checks the dimming rules */
1483 g_object_unref (toolbar_rules_group);
1484 g_object_unref (clipboard_rules_group);
1485 gtk_widget_hide (priv->priority_icon);
1486 gtk_widget_queue_resize (priv->subject_box);
1487 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1489 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1491 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1492 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1493 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1494 priv->update_caption_visibility = TRUE;
1496 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1498 /* Track account-removed signal, this window should be closed
1499 in the case we're creating a mail associated to the account
1501 priv->account_removed_handler_id =
1502 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1504 G_CALLBACK(on_account_removed),
1507 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1509 return (ModestWindow*) obj;
1513 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1515 GString **string_buffer = (GString **) user_data;
1517 *string_buffer = g_string_append (*string_buffer, buffer);
1523 * @result: A new string which should be freed with g_free().
1526 get_formatted_data (ModestMsgEditWindow *edit_window)
1528 ModestMsgEditWindowPrivate *priv;
1529 GString *string_buffer = g_string_new ("");
1531 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1533 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1535 modest_text_utils_hyperlinkify (string_buffer);
1537 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1539 return g_string_free (string_buffer, FALSE);
1544 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1547 const gchar *account_name;
1548 ModestMsgEditWindowPrivate *priv;
1549 TnyIterator *att_iter;
1551 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1553 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1555 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1556 g_return_val_if_fail (account_name, NULL);
1559 /* don't free these (except from) */
1560 data = g_slice_new0 (MsgData);
1561 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1563 data->account_name = g_strdup (account_name);
1564 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1565 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1566 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1567 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1568 if (priv->draft_msg) {
1569 data->draft_msg = g_object_ref (priv->draft_msg);
1570 } else if (priv->outbox_msg) {
1571 data->draft_msg = g_object_ref (priv->outbox_msg);
1573 data->draft_msg = NULL;
1576 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1578 gtk_text_buffer_get_bounds (buf, &b, &e);
1579 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1581 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1582 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1584 data->html_body = NULL;
1586 /* deep-copy the data */
1587 att_iter = tny_list_create_iterator (priv->attachments);
1588 data->attachments = NULL;
1589 while (!tny_iterator_is_done (att_iter)) {
1590 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1591 if (!(TNY_IS_MIME_PART(part))) {
1592 g_warning ("strange data in attachment list");
1593 g_object_unref (part);
1594 tny_iterator_next (att_iter);
1597 data->attachments = g_list_append (data->attachments,
1599 tny_iterator_next (att_iter);
1601 g_object_unref (att_iter);
1603 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1604 att_iter = tny_list_create_iterator (priv->images);
1605 data->images = NULL;
1606 while (!tny_iterator_is_done (att_iter)) {
1607 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1609 if (!(TNY_IS_MIME_PART(part))) {
1610 g_warning ("strange data in attachment list");
1611 g_object_unref (part);
1612 tny_iterator_next (att_iter);
1615 cid = tny_mime_part_get_content_id (part);
1617 gchar *image_tag_id;
1618 GtkTextTag *image_tag;
1620 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1621 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1622 g_free (image_tag_id);
1624 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1626 ((gtk_text_iter_has_tag (&iter, image_tag))||
1627 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1628 data->images = g_list_append (data->images,
1629 g_object_ref (part));
1631 g_object_unref (part);
1632 tny_iterator_next (att_iter);
1634 g_object_unref (att_iter);
1636 data->priority_flags = priv->priority_flags;
1643 unref_gobject (GObject *obj, gpointer data)
1645 if (!G_IS_OBJECT(obj))
1647 g_object_unref (obj);
1651 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1654 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1662 g_free (data->from);
1663 g_free (data->subject);
1664 g_free (data->plain_body);
1665 g_free (data->html_body);
1666 g_free (data->account_name);
1668 if (data->draft_msg != NULL) {
1669 g_object_unref (data->draft_msg);
1670 data->draft_msg = NULL;
1673 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1674 g_list_free (data->attachments);
1675 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1676 g_list_free (data->images);
1678 g_slice_free (MsgData, data);
1682 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1684 guint64 *parts_size)
1686 ModestMsgEditWindowPrivate *priv;
1688 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1690 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1692 /* TODO: add images */
1693 *parts_size += priv->images_size;
1694 *parts_count += priv->images_count;
1699 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1702 ModestMsgEditWindowPrivate *priv = NULL;
1703 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1705 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1707 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1709 return MODEST_MSG_EDIT_FORMAT_HTML;
1711 return MODEST_MSG_EDIT_FORMAT_TEXT;
1715 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1716 ModestMsgEditFormat format)
1718 ModestMsgEditWindowPrivate *priv;
1720 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1721 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1724 case MODEST_MSG_EDIT_FORMAT_HTML:
1725 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1727 case MODEST_MSG_EDIT_FORMAT_TEXT:
1728 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1731 g_return_if_reached ();
1735 ModestMsgEditFormatState *
1736 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1738 ModestMsgEditFormatState *format_state = NULL;
1739 ModestMsgEditWindowPrivate *priv;
1740 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1742 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1743 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1745 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1747 format_state = g_new0 (ModestMsgEditFormatState, 1);
1748 format_state->bold = buffer_format->bold&0x1;
1749 format_state->italics = buffer_format->italic&0x1;
1750 format_state->bullet = buffer_format->bullet&0x1;
1751 format_state->color = buffer_format->color;
1752 format_state->font_size = buffer_format->font_size;
1753 format_state->font_family = wp_get_font_name (buffer_format->font);
1754 format_state->justification = buffer_format->justification;
1755 g_free (buffer_format);
1757 return format_state;
1762 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1763 const ModestMsgEditFormatState *format_state)
1765 ModestMsgEditWindowPrivate *priv;
1766 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1767 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1768 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1769 g_return_if_fail (format_state != NULL);
1771 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1772 gtk_widget_grab_focus (priv->msg_body);
1773 buffer_format->bold = (format_state->bold != FALSE);
1774 buffer_format->italic = (format_state->italics != FALSE);
1775 buffer_format->color = format_state->color;
1776 buffer_format->font_size = format_state->font_size;
1777 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1778 buffer_format->justification = format_state->justification;
1779 buffer_format->bullet = format_state->bullet;
1781 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1783 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1784 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1785 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1786 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1787 buffer_format->cs.font = (buffer_format->font != current_format->font);
1788 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1789 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1791 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1792 if (buffer_format->cs.bold) {
1793 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1794 GINT_TO_POINTER (buffer_format->bold&0x1));
1796 if (buffer_format->cs.italic) {
1797 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1798 GINT_TO_POINTER (buffer_format->italic&0x1));
1800 if (buffer_format->cs.color) {
1801 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1802 GINT_TO_POINTER (&(buffer_format->color)));
1804 if (buffer_format->cs.font_size) {
1805 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1806 GINT_TO_POINTER (buffer_format->font_size));
1808 if (buffer_format->cs.justification) {
1809 switch (buffer_format->justification) {
1810 case GTK_JUSTIFY_LEFT:
1811 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1812 GINT_TO_POINTER(TRUE));
1814 case GTK_JUSTIFY_CENTER:
1815 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1816 GINT_TO_POINTER(TRUE));
1818 case GTK_JUSTIFY_RIGHT:
1819 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1820 GINT_TO_POINTER(TRUE));
1827 if (buffer_format->cs.font) {
1828 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1829 GINT_TO_POINTER (buffer_format->font));
1831 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1832 if (buffer_format->cs.bullet) {
1833 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1834 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1836 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1838 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1840 g_free (buffer_format);
1841 g_free (current_format);
1843 /* Check dimming rules */
1844 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1845 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1849 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1851 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1853 ModestWindowPrivate *parent_priv;
1854 ModestMsgEditWindowPrivate *priv;
1856 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1857 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1859 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1860 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1861 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1862 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1864 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1865 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1866 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1869 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1871 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1872 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1874 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1875 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1877 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1878 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1881 switch (buffer_format->justification)
1883 case GTK_JUSTIFY_LEFT:
1884 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1886 case GTK_JUSTIFY_CENTER:
1887 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1889 case GTK_JUSTIFY_RIGHT:
1890 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1897 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1899 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1900 G_CALLBACK (modest_msg_edit_window_color_button_change),
1902 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1903 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1904 G_CALLBACK (modest_msg_edit_window_color_button_change),
1907 if (priv->current_size_index != buffer_format->font_size) {
1911 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
1912 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
1916 priv->current_size_index = buffer_format->font_size;
1918 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
1919 markup = g_strconcat ("<span font_family='Sans'>",
1920 size_text, "</span>", NULL);
1922 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1926 gtk_tree_path_free (path);
1929 if (priv->current_face_index != buffer_format->font) {
1933 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
1934 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
1938 priv->current_face_index = buffer_format->font;
1939 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
1940 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
1941 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1948 g_free (buffer_format);
1952 #ifdef MODEST_HILDON_VERSION_0
1954 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1957 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1958 ModestMsgEditWindowPrivate *priv;
1959 GtkWidget *dialog = NULL;
1961 GdkColor *new_color = NULL;
1963 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1964 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1966 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1967 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1968 g_free (buffer_format);
1970 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
1971 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1972 if (new_color != NULL) {
1973 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1974 (gpointer) new_color);
1977 gtk_widget_destroy (dialog);
1982 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1985 ModestMsgEditWindowPrivate *priv;
1986 GtkWidget *dialog = NULL;
1988 GdkColor *old_color = NULL;
1989 const GdkColor *new_color = NULL;
1991 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1992 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1994 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1995 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1997 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
1998 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1999 if (new_color != NULL)
2000 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2002 gtk_widget_destroy (dialog);
2008 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2011 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2012 ModestMsgEditWindowPrivate *priv;
2013 GtkWidget *dialog = NULL;
2015 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2016 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2018 dialog = hildon_color_chooser_new ();
2019 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2020 g_free (buffer_format);
2022 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2024 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2025 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2028 gtk_widget_destroy (dialog);
2033 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2036 ModestMsgEditWindowPrivate *priv;
2037 GtkWidget *dialog = NULL;
2038 GdkColor *old_color = NULL;
2040 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2041 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2043 dialog = hildon_color_chooser_new ();
2044 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2046 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2048 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2049 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2051 gtk_widget_destroy (dialog);
2054 #endif /*!MODEST_HILDON_VERSION_0*/
2059 create_stream_for_uri (const gchar* uri)
2064 TnyStream *result = NULL;
2066 GnomeVFSHandle *handle = NULL;
2067 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2068 if (test == GNOME_VFS_OK) {
2069 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2070 /* Streams over OBEX (Bluetooth) are not seekable but
2071 * we expect them to be (we might need to read them
2072 * several times). So if this is a Bluetooth URI just
2073 * read the whole file into memory (this is not a fast
2074 * protocol so we can assume that these files are not
2075 * going to be very big) */
2076 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2077 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2078 TnyStream *memstream = tny_camel_mem_stream_new ();
2079 tny_stream_write_to_stream (vfssstream, memstream);
2080 g_object_unref (vfssstream);
2083 result = vfssstream;
2091 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2094 ModestMsgEditWindowPrivate *priv;
2095 GtkWidget *dialog = NULL;
2097 GSList *uris = NULL;
2098 GSList *uri_node = NULL;
2100 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2102 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2103 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2104 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2106 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2108 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2109 GTK_WINDOW (dialog), GTK_WINDOW (window));
2111 response = gtk_dialog_run (GTK_DIALOG (dialog));
2113 case GTK_RESPONSE_OK:
2114 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2119 gtk_widget_destroy (dialog);
2121 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2123 GnomeVFSHandle *handle = NULL;
2124 GnomeVFSResult result;
2125 GtkTextIter position;
2126 GtkTextMark *insert_mark;
2128 uri = (const gchar *) uri_node->data;
2129 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2130 if (result == GNOME_VFS_OK) {
2132 GnomeVFSFileInfo *info;
2133 gchar *filename, *basename, *escaped_filename;
2134 TnyMimePart *mime_part;
2136 const gchar *mime_type = NULL;
2137 GnomeVFSURI *vfs_uri;
2138 guint64 stream_size;
2140 gnome_vfs_close (handle);
2141 vfs_uri = gnome_vfs_uri_new (uri);
2143 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2144 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2145 g_free (escaped_filename);
2146 gnome_vfs_uri_unref (vfs_uri);
2147 info = gnome_vfs_file_info_new ();
2149 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2150 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2152 mime_type = gnome_vfs_file_info_get_mime_type (info);
2154 mime_part = tny_platform_factory_new_mime_part
2155 (modest_runtime_get_platform_factory ());
2157 TnyStream *stream = create_stream_for_uri (uri);
2159 if (stream == NULL) {
2161 modest_platform_information_banner (NULL, NULL,
2162 _FM("sfil_ib_opening_not_allowed"));
2164 g_object_unref (mime_part);
2165 gnome_vfs_file_info_unref (info);
2169 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2171 content_id = g_strdup_printf ("%d", priv->next_cid);
2172 tny_mime_part_set_content_id (mime_part, content_id);
2173 g_free (content_id);
2176 basename = g_path_get_basename (filename);
2177 tny_mime_part_set_filename (mime_part, basename);
2180 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2182 if (pixbuf != NULL) {
2183 priv->images_size += stream_size;
2184 priv->images_count ++;
2185 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2186 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2187 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2188 g_object_unref (pixbuf);
2191 tny_list_prepend (priv->images, (GObject *) mime_part);
2192 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2194 g_object_unref (mime_part);
2195 gnome_vfs_file_info_unref (info);
2204 on_attach_file_response (GtkDialog *dialog,
2208 GSList *uris = NULL;
2210 GnomeVFSFileSize total_size, allowed_size;
2211 ModestMsgEditWindow *window;
2212 ModestMsgEditWindowPrivate *priv;
2217 case GTK_RESPONSE_OK:
2218 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2224 window = MODEST_MSG_EDIT_WINDOW (user_data);
2225 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2227 /* allowed size is the maximum size - what's already there */
2228 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2229 &att_num, &att_size);
2230 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2233 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2235 const gchar *uri = (const gchar *) uri_node->data;
2238 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2240 if (total_size > allowed_size) {
2241 g_warning ("%s: total size: %u",
2242 __FUNCTION__, (unsigned int)total_size);
2245 allowed_size -= total_size;
2247 g_slist_foreach (uris, (GFunc) g_free, NULL);
2248 g_slist_free (uris);
2250 gtk_widget_destroy (GTK_WIDGET (dialog));
2254 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2256 GtkWidget *dialog = NULL;
2257 ModestMsgEditWindowPrivate *priv;
2259 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2261 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2263 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2266 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2267 GTK_FILE_CHOOSER_ACTION_OPEN);
2268 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2269 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2270 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2271 GTK_WINDOW (dialog), GTK_WINDOW (window));
2273 /* Connect to response & show */
2274 g_signal_connect (dialog, "response",
2275 G_CALLBACK (on_attach_file_response), window);
2276 gtk_widget_show (dialog);
2281 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2283 GnomeVFSFileSize allowed_size)
2286 GnomeVFSHandle *handle = NULL;
2287 ModestMsgEditWindowPrivate *priv;
2288 GnomeVFSResult result;
2289 GnomeVFSFileSize size = 0;
2290 g_return_val_if_fail (window, 0);
2291 g_return_val_if_fail (uri, 0);
2293 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2295 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2296 if (result == GNOME_VFS_OK) {
2297 TnyMimePart *mime_part;
2299 const gchar *mime_type = NULL;
2301 gchar *escaped_filename;
2304 GnomeVFSFileInfo *info;
2305 GnomeVFSURI *vfs_uri;
2307 gnome_vfs_close (handle);
2308 vfs_uri = gnome_vfs_uri_new (uri);
2311 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2312 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2313 g_free (escaped_filename);
2314 gnome_vfs_uri_unref (vfs_uri);
2316 info = gnome_vfs_file_info_new ();
2318 if (gnome_vfs_get_file_info (uri,
2320 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2322 mime_type = gnome_vfs_file_info_get_mime_type (info);
2323 mime_part = tny_platform_factory_new_mime_part
2324 (modest_runtime_get_platform_factory ());
2326 /* try to get the attachment's size; this may fail for weird
2327 * file systems, like obex, upnp... */
2328 if (allowed_size != 0 &&
2329 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2331 if (size > allowed_size) {
2332 modest_platform_information_banner (NULL, NULL,
2333 _FM("sfil_ib_opening_not_allowed"));
2337 g_warning ("%s: could not get attachment size", __FUNCTION__);
2339 stream = create_stream_for_uri (uri);
2341 if (stream == NULL) {
2343 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2345 g_object_unref (mime_part);
2346 gnome_vfs_file_info_unref (info);
2350 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2351 g_object_unref (stream);
2353 content_id = g_strdup_printf ("%d", priv->next_cid);
2354 tny_mime_part_set_content_id (mime_part, content_id);
2355 g_free (content_id);
2358 basename = g_path_get_basename (filename);
2359 tny_mime_part_set_filename (mime_part, basename);
2362 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2363 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2365 info->size == 0, info->size);
2366 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2367 gtk_widget_show_all (priv->attachments_caption);
2368 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2370 g_object_unref (mime_part);
2371 gnome_vfs_file_info_unref (info);
2378 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2381 ModestMsgEditWindowPrivate *priv;
2384 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2385 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2387 if (att_list == NULL) {
2388 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2389 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2390 g_object_unref (att_list);
2395 g_object_ref (att_list);
2398 if (tny_list_get_length (att_list) == 0) {
2399 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2401 gboolean dialog_response;
2402 gchar *message = NULL;
2403 gchar *filename = NULL;
2405 if (tny_list_get_length (att_list) == 1) {
2407 iter = tny_list_create_iterator (att_list);
2408 part = (TnyMimePart *) tny_iterator_get_current (iter);
2409 g_object_unref (iter);
2410 if (TNY_IS_MSG (part)) {
2411 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2413 filename = tny_header_dup_subject (header);
2414 g_object_unref (header);
2416 if (filename == NULL) {
2417 filename = g_strdup (_("mail_va_no_subject"));
2420 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2422 g_object_unref (part);
2424 filename = g_strdup ("");
2426 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2427 "emev_nc_delete_attachments",
2428 tny_list_get_length (att_list)), filename);
2431 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2435 if (dialog_response != GTK_RESPONSE_OK) {
2436 g_object_unref (att_list);
2440 for (iter = tny_list_create_iterator (att_list);
2441 !tny_iterator_is_done (iter);
2442 tny_iterator_next (iter)) {
2443 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2444 const gchar *att_id;
2445 tny_list_remove (priv->attachments, (GObject *) mime_part);
2447 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2449 if (tny_list_get_length (priv->attachments) == 0)
2450 gtk_widget_hide (priv->attachments_caption);
2451 att_id = tny_mime_part_get_content_id (mime_part);
2453 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2455 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2456 g_object_unref (mime_part);
2458 g_object_unref (iter);
2461 g_object_unref (att_list);
2463 /* if the last attachment has been removed, focus the Subject: field */
2464 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2465 gtk_widget_grab_focus (priv->subject_field);
2469 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2472 ModestMsgEditWindowPrivate *priv;
2473 GdkColor *new_color;
2474 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2476 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2477 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2480 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2482 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2484 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2486 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2491 font_size_clicked (GtkToolButton *button,
2492 ModestMsgEditWindow *window)
2494 ModestMsgEditWindowPrivate *priv;
2495 GtkWidget *selector, *dialog;
2497 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2499 selector = hildon_touch_selector_new ();
2500 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2501 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2503 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2504 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2506 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2510 WPTextBufferFormat format;
2512 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2514 memset (&format, 0, sizeof (format));
2515 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2517 format.cs.font_size = TRUE;
2518 format.cs.text_position = TRUE;
2519 format.cs.font = TRUE;
2520 format.font_size = new_index;
2521 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2523 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2524 GINT_TO_POINTER (new_index)))
2525 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2527 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2528 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2529 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2530 size_text, "</span>", NULL);
2532 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2536 gtk_widget_destroy (dialog);
2538 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2543 font_face_clicked (GtkToolButton *button,
2544 ModestMsgEditWindow *window)
2546 ModestMsgEditWindowPrivate *priv;
2547 GtkWidget *selector, *dialog;
2548 GtkCellRenderer *renderer;
2550 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2552 selector = hildon_touch_selector_new ();
2553 renderer = gtk_cell_renderer_text_new ();
2554 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2555 renderer, "family", 0, "text", 0, NULL);
2556 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2558 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2559 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2561 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2562 gint new_font_index;
2566 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2567 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2568 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2572 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2574 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2575 GINT_TO_POINTER(new_font_index)))
2576 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2578 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2579 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2581 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2585 gtk_tree_path_free (path);
2588 gtk_widget_destroy (dialog);
2590 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2595 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2598 ModestMsgEditWindowPrivate *priv = NULL;
2599 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2601 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2602 if (!priv->update_caption_visibility)
2605 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2607 gtk_widget_show (priv->cc_caption);
2609 gtk_widget_hide (priv->cc_caption);
2611 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2615 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2618 ModestMsgEditWindowPrivate *priv = NULL;
2619 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2621 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2622 if (!priv->update_caption_visibility)
2625 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2627 gtk_widget_show (priv->bcc_caption);
2629 gtk_widget_hide (priv->bcc_caption);
2631 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2635 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2636 ModestRecptEditor *editor)
2638 ModestMsgEditWindowPrivate *priv;
2640 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2641 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2643 /* we check for low-mem; in that case, show a warning, and don't allow
2644 * for the addressbook
2646 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2649 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2651 if (editor == NULL) {
2652 GtkWidget *view_focus;
2653 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2655 /* This code should be kept in sync with ModestRecptEditor. The
2656 textview inside the recpt editor is the one that really gets the
2657 focus. As it's inside a scrolled window, and this one inside the
2658 hbox recpt editor inherits from, we'll need to go up in the
2659 hierarchy to know if the text view is part of the recpt editor
2660 or if it's a different text entry */
2662 if (gtk_widget_get_parent (view_focus)) {
2663 GtkWidget *first_parent;
2665 first_parent = gtk_widget_get_parent (view_focus);
2666 if (gtk_widget_get_parent (first_parent) &&
2667 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2668 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2673 editor = MODEST_RECPT_EDITOR (priv->to_field);
2677 modest_address_book_select_addresses (editor);
2682 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2684 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2686 modest_msg_edit_window_open_addressbook (window, NULL);
2690 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2691 gboolean show_toolbar)
2693 ModestWindowPrivate *parent_priv;
2695 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2696 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2698 /* We can not just use the code of
2699 modest_msg_edit_window_setup_toolbar because it has a
2700 mixture of both initialization and creation code. */
2702 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2704 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2708 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2709 TnyHeaderFlags priority_flags)
2711 ModestMsgEditWindowPrivate *priv;
2712 ModestWindowPrivate *parent_priv;
2714 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2716 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2717 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2719 if (priv->priority_flags != priority_flags) {
2720 GtkAction *priority_action = NULL;
2722 priv->priority_flags = priority_flags;
2724 switch (priority_flags) {
2725 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2726 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2727 MODEST_HEADER_ICON_HIGH,
2728 HILDON_ICON_SIZE_SMALL);
2729 gtk_widget_show (priv->priority_icon);
2730 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2731 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2733 case TNY_HEADER_FLAG_LOW_PRIORITY:
2734 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2735 MODEST_HEADER_ICON_LOW,
2736 HILDON_ICON_SIZE_SMALL);
2737 gtk_widget_show (priv->priority_icon);
2738 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2739 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2742 gtk_widget_hide (priv->priority_icon);
2743 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2744 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2747 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2748 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2750 gtk_widget_queue_resize (priv->subject_box);
2754 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2757 ModestMsgEditWindowPrivate *priv;
2758 ModestWindowPrivate *parent_priv;
2759 gint current_format;
2761 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2763 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2764 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2766 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2767 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2769 if (current_format != file_format) {
2770 switch (file_format) {
2771 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2772 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2773 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2775 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2779 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2780 response = gtk_dialog_run (GTK_DIALOG (dialog));
2781 gtk_widget_destroy (dialog);
2782 if (response == GTK_RESPONSE_OK) {
2783 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2785 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2786 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2791 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2792 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2793 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2798 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2801 ModestMsgEditWindowPrivate *priv;
2802 WPTextBufferFormat oldfmt, fmt;
2803 gint old_position = 0;
2807 GdkColor *color = NULL;
2808 gboolean bold, bold_set, italic, italic_set;
2809 gboolean underline, underline_set;
2810 gboolean strikethrough, strikethrough_set;
2811 gboolean position_set;
2812 gboolean font_size_set, font_set, color_set;
2815 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2816 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2818 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2819 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2820 GTK_WINDOW(dialog), GTK_WINDOW (window));
2822 /* First we get the currently selected font information */
2823 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2825 switch (oldfmt.text_position) {
2826 case TEXT_POSITION_NORMAL:
2829 case TEXT_POSITION_SUPERSCRIPT:
2837 g_object_set (G_OBJECT (dialog),
2838 "bold", oldfmt.bold != FALSE,
2839 "bold-set", !oldfmt.cs.bold,
2840 "underline", oldfmt.underline != FALSE,
2841 "underline-set", !oldfmt.cs.underline,
2842 "italic", oldfmt.italic != FALSE,
2843 "italic-set", !oldfmt.cs.italic,
2844 "strikethrough", oldfmt.strikethrough != FALSE,
2845 "strikethrough-set", !oldfmt.cs.strikethrough,
2846 "color", &oldfmt.color,
2847 "color-set", !oldfmt.cs.color,
2848 "size", wp_font_size[oldfmt.font_size],
2849 "size-set", !oldfmt.cs.font_size,
2850 "position", old_position,
2851 "position-set", !oldfmt.cs.text_position,
2852 "family", wp_get_font_name (oldfmt.font),
2853 "family-set", !oldfmt.cs.font,
2856 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2857 GTK_WINDOW (dialog), GTK_WINDOW (window));
2858 gtk_widget_show_all (dialog);
2859 priv->font_dialog = dialog;
2860 response = gtk_dialog_run (GTK_DIALOG (dialog));
2861 priv->font_dialog = NULL;
2862 if (response == GTK_RESPONSE_OK) {
2864 g_object_get( dialog,
2866 "bold-set", &bold_set,
2867 "underline", &underline,
2868 "underline-set", &underline_set,
2870 "italic-set", &italic_set,
2871 "strikethrough", &strikethrough,
2872 "strikethrough-set", &strikethrough_set,
2874 "color-set", &color_set,
2876 "size-set", &font_size_set,
2877 "family", &font_name,
2878 "family-set", &font_set,
2879 "position", &position,
2880 "position-set", &position_set,
2885 if (response == GTK_RESPONSE_OK) {
2886 memset(&fmt, 0, sizeof(fmt));
2892 fmt.italic = italic;
2893 fmt.cs.italic = TRUE;
2895 if (underline_set) {
2896 fmt.underline = underline;
2897 fmt.cs.underline = TRUE;
2899 if (strikethrough_set) {
2900 fmt.strikethrough = strikethrough;
2901 fmt.cs.strikethrough = TRUE;
2906 ? TEXT_POSITION_NORMAL
2907 : ( ( position == 1 )
2908 ? TEXT_POSITION_SUPERSCRIPT
2909 : TEXT_POSITION_SUBSCRIPT );
2910 fmt.cs.text_position = TRUE;
2911 fmt.font_size = oldfmt.font_size;
2915 fmt.cs.color = TRUE;
2918 fmt.font = wp_get_font_index(font_name,
2923 if (font_size_set) {
2924 fmt.cs.font_size = TRUE;
2925 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2927 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2928 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2930 gtk_widget_destroy (dialog);
2932 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2936 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2938 ModestMsgEditWindowPrivate *priv;
2940 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2941 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2943 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2945 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2946 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2950 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2952 ModestMsgEditWindowPrivate *priv;
2954 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2955 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2957 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2959 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2960 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2965 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2967 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2969 priv->can_undo = can_undo;
2973 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2975 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2977 priv->can_redo = can_redo;
2981 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2983 ModestMsgEditWindowPrivate *priv;
2984 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2985 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2987 return priv->can_undo;
2991 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2993 ModestMsgEditWindowPrivate *priv;
2994 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2995 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2997 return priv->can_redo;
3002 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3005 GtkTextIter match_start, match_end;
3007 if (image_id == NULL)
3010 gtk_text_buffer_get_start_iter (buffer, &iter);
3012 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3013 GSList *tags = gtk_text_iter_get_tags (&match_start);
3015 for (node = tags; node != NULL; node = g_slist_next (node)) {
3016 GtkTextTag *tag = (GtkTextTag *) node->data;
3017 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3018 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3019 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3021 offset = gtk_text_iter_get_offset (&match_start);
3022 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3023 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3027 gtk_text_iter_forward_char (&iter);
3032 message_is_empty (ModestMsgEditWindow *window)
3034 ModestMsgEditWindowPrivate *priv = NULL;
3036 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3037 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3039 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3040 * so we can ignore markup.
3042 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3045 count = gtk_text_buffer_get_char_count (buf);
3051 msg_body_focus (GtkWidget *focus,
3052 GdkEventFocus *event,
3056 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3057 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3058 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3063 recpt_field_changed (GtkTextBuffer *buffer,
3064 ModestMsgEditWindow *editor)
3066 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3067 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3071 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3073 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3074 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3078 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3081 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3082 GtkTextBuffer *buffer;
3084 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3085 gtk_text_buffer_set_modified (buffer, modified);
3086 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3087 gtk_text_buffer_set_modified (buffer, modified);
3088 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3089 gtk_text_buffer_set_modified (buffer, modified);
3090 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3094 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3096 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3097 const char *account_name;
3098 GtkTextBuffer *buffer;
3100 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3101 if (gtk_text_buffer_get_modified (buffer))
3103 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3104 if (gtk_text_buffer_get_modified (buffer))
3106 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3107 if (gtk_text_buffer_get_modified (buffer))
3109 if (gtk_text_buffer_get_modified (priv->text_buffer))
3111 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3112 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3123 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3125 ModestMsgEditWindowPrivate *priv = NULL;
3127 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3128 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3130 /* check if there's no recipient added */
3131 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3132 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3133 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3134 /* no recipient contents, then select contacts */
3135 modest_msg_edit_window_open_addressbook (window, NULL);
3139 g_object_ref (window);
3140 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3141 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3142 g_object_unref (window);
3145 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3146 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3147 g_object_unref (window);
3150 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3151 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3152 g_object_unref (window);
3156 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3157 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3158 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3159 g_object_unref (window);
3166 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3167 ModestMsgEditWindow *window)
3169 modest_msg_edit_window_offer_attach_file (window);
3173 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3175 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3177 return priv->clipboard_text;
3181 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3183 ModestMsgEditWindow *window)
3185 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3186 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3188 if (!GTK_WIDGET_VISIBLE (window))
3191 g_object_ref (window);
3192 text = gtk_clipboard_wait_for_text (selection_clipboard);
3194 if (priv->clipboard_text != NULL) {
3195 g_free (priv->clipboard_text);
3197 priv->clipboard_text = text;
3199 if (GTK_WIDGET_VISIBLE (window)) {
3200 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3202 g_object_unref (window);
3205 static gboolean clipboard_owner_change_idle (gpointer userdata)
3207 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3208 ModestMsgEditWindowPrivate *priv;
3210 gdk_threads_enter ();
3211 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3212 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3214 priv->clipboard_owner_idle = 0;
3215 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3216 gdk_threads_leave ();
3222 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3224 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3225 if (priv->clipboard_owner_idle == 0) {
3226 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3231 subject_field_move_cursor (GtkEntry *entry,
3232 GtkMovementStep step,
3237 if (!GTK_WIDGET_VISIBLE (window))
3240 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3244 update_window_title (ModestMsgEditWindow *window)
3246 ModestMsgEditWindowPrivate *priv = NULL;
3247 const gchar *subject;
3249 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3250 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3251 if (subject == NULL || subject[0] == '\0')
3252 subject = _("mail_va_new_email");
3254 gtk_window_set_title (GTK_WINDOW (window), subject);
3259 subject_field_changed (GtkEditable *editable,
3260 ModestMsgEditWindow *window)
3262 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3263 update_window_title (window);
3264 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3265 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3266 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3270 subject_field_insert_text (GtkEditable *editable,
3272 gint new_text_length,
3274 ModestMsgEditWindow *window)
3276 GString *result = g_string_new ("");
3278 gint result_len = 0;
3279 const gchar *entry_text = NULL;
3282 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3283 old_length = g_utf8_strlen (entry_text, -1);
3285 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3286 gunichar c = g_utf8_get_char_validated (current, 8);
3287 /* Invalid unichar, stop */
3293 result = g_string_append_unichar (result, c);
3297 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3298 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3301 /* Prevent endless recursion */
3302 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3303 g_signal_emit_by_name (editable, "insert-text",
3304 (gpointer) result->str, (gpointer) result->len,
3305 (gpointer) position, (gpointer) window);
3306 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3310 if (result_len + old_length > 1000) {
3311 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3312 _CS("ckdg_ib_maximum_characters_reached"));
3314 g_string_free (result, TRUE);
3318 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3321 ModestMsgEditWindowPrivate *priv = NULL;
3323 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3324 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3326 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3329 gtk_widget_show_all (priv->find_toolbar);
3330 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3332 gtk_widget_hide_all (priv->find_toolbar);
3333 gtk_widget_grab_focus (priv->msg_body);
3338 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3340 GtkTextIter *match_start,
3341 GtkTextIter *match_end)
3343 GtkTextIter end_iter;
3344 gchar *str_casefold;
3347 gchar *range_casefold;
3350 gboolean result = FALSE;
3357 gtk_text_iter_forward_to_end (&end_iter);
3359 str_casefold = g_utf8_casefold (str, -1);
3360 str_chars_n = strlen (str);
3362 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3363 range_casefold = g_utf8_casefold (range_text, -1);
3364 range_chars_n = strlen (range_casefold);
3366 if (range_chars_n < str_chars_n) {
3367 g_free (str_casefold);
3368 g_free (range_text);
3369 g_free (range_casefold);
3373 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3374 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3375 if (!g_utf8_collate (range_subtext, str_casefold)) {
3376 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3378 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3379 match_start, match_end, NULL);
3380 g_free (found_text);
3382 g_free (range_subtext);
3386 g_free (str_casefold);
3387 g_free (range_text);
3388 g_free (range_casefold);
3395 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3396 ModestMsgEditWindow *window)
3398 gchar *current_search = NULL;
3399 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3401 GtkTextIter selection_start, selection_end;
3402 GtkTextIter match_start, match_end;
3403 gboolean continue_search = FALSE;
3405 if (message_is_empty (window)) {
3406 g_free (priv->last_search);
3407 priv->last_search = NULL;
3408 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3412 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3413 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3414 g_free (current_search);
3415 g_free (priv->last_search);
3416 priv->last_search = NULL;
3417 /* Information banner about empty search */
3418 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3422 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3423 continue_search = TRUE;
3425 g_free (priv->last_search);
3426 priv->last_search = g_strdup (current_search);
3429 if (continue_search) {
3430 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3431 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3432 &match_start, &match_end);
3434 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3436 GtkTextIter buffer_start;
3437 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3438 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3439 &match_start, &match_end);
3441 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3444 /* Mark as selected the string found in search */
3446 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3447 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3448 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3450 g_free (priv->last_search);
3451 priv->last_search = NULL;
3453 g_free (current_search);
3457 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3459 ModestMsgEditWindowPrivate *priv;
3461 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3466 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3469 ModestMsgEditWindowPrivate *priv;
3471 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3476 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3477 ModestMsgEditWindow *window)
3479 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3483 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3486 ModestMsgEditWindowPrivate *priv;
3487 TnyHeader *header = NULL;
3489 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3490 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3492 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3493 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3495 if (priv->draft_msg != NULL) {
3496 g_object_unref (priv->draft_msg);
3499 if (draft != NULL) {
3500 g_object_ref (draft);
3501 header = tny_msg_get_header (draft);
3502 if (priv->msg_uid) {
3503 g_free (priv->msg_uid);
3504 priv->msg_uid = NULL;
3506 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3507 if (GTK_WIDGET_REALIZED (window)) {
3508 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3509 gtk_widget_destroy (GTK_WIDGET (window));
3515 priv->draft_msg = draft;
3519 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3520 GtkTextIter *start, GtkTextIter *end,
3523 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3524 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3527 if (tag == NULL) return;
3528 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3529 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3530 replace_with_images (window, priv->images);
3535 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3538 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3540 g_return_if_fail (TNY_IS_MIME_PART (part));
3541 tny_list_prepend (priv->attachments, (GObject *) part);
3542 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3543 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3544 gtk_widget_show_all (priv->attachments_caption);
3545 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3549 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3551 ModestMsgEditWindowPrivate *priv;
3553 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3554 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3556 return priv->msg_uid;
3560 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3561 ModestMsgEditWindowWidgetType widget_type)
3563 ModestMsgEditWindowPrivate *priv;
3565 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3566 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3568 switch (widget_type) {
3569 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3570 return priv->msg_body;
3572 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3573 return priv->to_field;
3575 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3576 return priv->cc_field;
3578 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3579 return priv->bcc_field;
3581 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3582 return priv->subject_field;
3584 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3585 return priv->attachments_view;
3593 remove_tags (WPTextBuffer *buffer)
3595 GtkTextIter start, end;
3597 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3598 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3600 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3604 on_account_removed (TnyAccountStore *account_store,
3605 TnyAccount *account,
3608 /* Do nothing if it's a store account, because we use the
3609 transport to send the messages */
3610 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3611 const gchar *parent_acc = NULL;
3612 const gchar *our_acc = NULL;
3614 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3615 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3616 /* Close this window if I'm showing a message of the removed account */
3617 if (strcmp (parent_acc, our_acc) == 0)
3618 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3623 from_field_changed (HildonPickerButton *button,
3624 ModestMsgEditWindow *self)
3626 ModestMsgEditWindowPrivate *priv;
3627 gboolean has_old_signature, has_new_signature;
3629 GtkTextIter match_start, match_end;
3630 ModestAccountMgr *mgr;
3632 gchar *full_signature;
3634 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3636 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3637 mgr = modest_runtime_get_account_mgr ();
3638 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3639 if (has_old_signature) {
3640 full_signature = g_strconcat ("\n--\n", signature, NULL);
3641 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3642 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3644 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3645 &match_start, &match_end, NULL)) {
3648 g_free (full_signature);
3652 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3653 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3654 if (has_new_signature) {
3655 full_signature = g_strconcat ("\n--\n", signature, NULL);
3656 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3657 g_free (full_signature);
3662 typedef struct _MessageSettingsHelper {
3663 ModestMsgEditWindow *window;
3664 GSList *priority_group;
3665 GSList *format_group;
3666 GtkToggleButton *current_priority;
3667 GtkToggleButton *current_format;
3668 } MessageSettingsHelper;
3671 on_priority_toggle (GtkToggleButton *button,
3672 MessageSettingsHelper *helper)
3675 ModestMsgEditWindowPrivate *priv;
3677 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3678 if (gtk_toggle_button_get_active (button)) {
3680 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3681 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3682 if ((node_button != button) &&
3683 gtk_toggle_button_get_active (node_button)) {
3684 gtk_toggle_button_set_active (node_button, FALSE);
3687 helper->current_priority = button;
3689 gboolean found = FALSE;
3690 /* If no one is active, activate it again */
3691 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3692 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3693 if (gtk_toggle_button_get_active (node_button)) {
3699 gtk_toggle_button_set_active (button, TRUE);
3705 on_format_toggle (GtkToggleButton *button,
3706 MessageSettingsHelper *helper)
3709 ModestMsgEditWindowPrivate *priv;
3711 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3712 if (gtk_toggle_button_get_active (button)) {
3714 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3715 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3716 if ((node_button != button) &&
3717 gtk_toggle_button_get_active (node_button)) {
3718 gtk_toggle_button_set_active (node_button, FALSE);
3721 helper->current_format = button;
3723 gboolean found = FALSE;
3724 /* If no one is active, activate it again */
3725 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3726 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3727 if (gtk_toggle_button_get_active (node_button)) {
3733 gtk_toggle_button_set_active (button, TRUE);
3740 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3745 GtkWidget *priority_hbox;
3746 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3747 GtkWidget *captioned;
3748 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3749 GtkWidget *format_hbox;
3750 GtkWidget *html_toggle, *text_toggle;
3751 ModestMsgEditWindowPrivate *priv;
3752 MessageSettingsHelper helper = {0,};
3754 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3755 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3756 helper.window = window;
3757 helper.priority_group = NULL;
3758 helper.format_group = NULL;
3760 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3761 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3763 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3764 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3765 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3766 vbox = gtk_vbox_new (FALSE, 0);
3767 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
3768 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
3769 gtk_container_add (GTK_CONTAINER (align), vbox);
3770 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
3771 gtk_widget_show (align);
3772 gtk_widget_show (vbox);
3774 /* Priority toggles */
3775 priority_hbox = gtk_hbox_new (TRUE, 0);
3776 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3777 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3778 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3779 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3780 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3781 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3782 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3783 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3784 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3785 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3786 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3787 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3788 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3789 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3790 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3791 gtk_widget_show_all (priority_hbox);
3792 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3793 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3794 gtk_widget_show (captioned);
3795 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3797 /* format toggles */
3798 format_hbox = gtk_hbox_new (TRUE, 0);
3799 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3800 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3801 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3802 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3803 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3804 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3805 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3806 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3807 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3808 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3809 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3810 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3811 gtk_widget_show_all (format_hbox);
3812 gtk_widget_show (format_hbox);
3813 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3816 g_object_unref (title_sizegroup);
3817 g_object_unref (value_sizegroup);
3819 /* Set current values */
3820 switch (priv->priority_flags) {
3821 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3822 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3823 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3825 case TNY_HEADER_FLAG_LOW_PRIORITY:
3826 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3827 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3830 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3831 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3835 switch (modest_msg_edit_window_get_format (window)) {
3836 case MODEST_MSG_EDIT_FORMAT_TEXT:
3837 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3838 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3840 case MODEST_MSG_EDIT_FORMAT_HTML:
3842 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3843 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3847 /* Signal connects */
3848 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3849 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3850 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3851 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3852 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3854 /* Save settings if the user clicked on done */
3855 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3856 TnyHeaderFlags flags;
3857 ModestMsgEditFormat old_format, new_format;
3859 /* Set priority flags */
3860 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3861 if (priv->priority_flags != flags)
3862 modest_msg_edit_window_set_priority_flags (window, flags);
3864 /* Set edit format */
3865 old_format = modest_msg_edit_window_get_format (window);
3866 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3867 if (old_format != new_format) {
3868 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3869 modest_msg_edit_window_set_file_format (window, file_format);
3873 gtk_widget_destroy (dialog);
3874 g_slist_free (helper.priority_group);
3878 on_message_settings (GtkAction *action,
3879 ModestMsgEditWindow *window)
3881 modest_msg_edit_window_show_msg_settings_dialog (window);
3885 on_cc_button_toggled (HildonCheckButton *button,
3886 ModestMsgEditWindow *window)
3888 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3890 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3891 hildon_check_button_get_active (button));
3895 on_bcc_button_toggled (HildonCheckButton *button,
3896 ModestMsgEditWindow *window)
3898 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3900 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3901 hildon_check_button_get_active (button));
3905 setup_menu (ModestMsgEditWindow *self)
3907 ModestMsgEditWindowPrivate *priv = NULL;
3909 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3911 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3913 /* Settings menu buttons */
3914 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3915 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3917 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3918 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3919 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3921 priv->cc_button = hildon_check_button_new (0);
3922 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3923 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3925 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3927 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3928 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3929 priv->bcc_button = hildon_check_button_new (0);
3930 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3931 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3933 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3935 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3936 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3938 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3939 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3940 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3941 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3942 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3943 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3944 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3945 APP_MENU_CALLBACK (on_message_settings),
3947 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3948 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),