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 <wptextview.h>
65 #include <wptextbuffer.h>
66 #include <hildon/hildon-pannable-area.h>
67 #include "modest-msg-edit-window-ui-dimming.h"
69 #include "modest-hildon-includes.h"
70 #ifdef MODEST_HAVE_HILDON0_WIDGETS
71 #include <hildon-widgets/hildon-color-chooser.h>
73 #include "widgets/modest-msg-edit-window-ui.h"
74 #ifdef MODEST_HAVE_HILDON0_WIDGETS
75 #include <libgnomevfs/gnome-vfs-mime-utils.h>
77 #include <libgnomevfs/gnome-vfs-mime.h>
79 #include <modest-utils.h>
80 #include "modest-maemo-utils.h"
81 #include <modest-ui-constants.h>
84 #define DEFAULT_FONT_SIZE 3
85 #define DEFAULT_FONT 2
86 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
87 #define DEFAULT_MAIN_VBOX_SPACING 6
88 #define SUBJECT_MAX_LENGTH 1000
89 #define IMAGE_MAX_WIDTH 560
90 #define DEFAULT_FONT_SCALE 1.5
92 static gboolean is_wp_text_buffer_started = FALSE;
94 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
95 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
96 static void modest_msg_edit_window_finalize (GObject *obj);
98 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
99 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
100 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
102 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
103 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
104 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
105 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
106 GtkTextIter *start, GtkTextIter *end,
108 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
109 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
110 static void subject_field_insert_text (GtkEditable *editable,
112 gint new_text_length,
114 ModestMsgEditWindow *window);
115 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
117 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
119 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
121 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
123 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
124 ModestRecptEditor *editor);
125 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
126 ModestMsgEditWindow *window);
128 /* ModestWindow methods implementation */
129 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
130 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
131 gboolean show_toolbar);
132 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
134 ModestMsgEditWindow *window);
135 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
136 static void subject_field_move_cursor (GtkEntry *entry,
137 GtkMovementStep step,
141 static void update_window_title (ModestMsgEditWindow *window);
144 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
145 ModestMsgEditWindow *window);
146 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
147 ModestMsgEditWindow *window);
148 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
150 GtkTextIter *match_start,
151 GtkTextIter *match_end);
153 static void remove_tags (WPTextBuffer *buffer);
155 static void on_account_removed (TnyAccountStore *account_store,
159 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
160 static void set_zoom_do_nothing (ModestWindow *window, gdouble zoom);
161 static gdouble get_zoom_do_nothing (ModestWindow *window);
163 static void init_window (ModestMsgEditWindow *obj);
165 gboolean scroll_drag_timeout (gpointer userdata);
166 static void correct_scroll (ModestMsgEditWindow *w);
167 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
168 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
169 ModestMsgEditWindow *userdata);
170 static void text_buffer_mark_set (GtkTextBuffer *buffer,
173 ModestMsgEditWindow *userdata);
174 static void on_message_settings (GtkAction *action,
175 ModestMsgEditWindow *window);
176 static void add_to_menu (ModestMsgEditWindow *self,
180 ModestDimmingRulesGroup *group,
181 GCallback dimming_callback);
182 static void setup_menu (ModestMsgEditWindow *self,
183 ModestDimmingRulesGroup *group);
184 static gboolean modest_msg_edit_window_toggle_menu (HildonWindow *window,
188 static void DEBUG_BUFFER (WPTextBuffer *buffer)
192 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
194 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
195 while (!gtk_text_iter_is_end (&iter)) {
196 GString *output = g_string_new ("");
197 GSList *toggled_tags;
200 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
201 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
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, "] OPENED [ ");
210 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
211 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
212 GtkTextTag *tag = (GtkTextTag *) node->data;
214 g_object_get (G_OBJECT (tag), "name", &name, NULL);
215 output = g_string_append (output, name);
216 g_string_append (output, " ");
218 output = g_string_append (output, "]\n");
219 g_message ("%s", output->str);
220 g_string_free (output, TRUE);
221 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
223 g_message ("END BUFFER");
227 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
228 { "MessageSettings", NULL, N_("TODO: settings..."), NULL, NULL, G_CALLBACK (on_message_settings)},
232 /* static gboolean */
233 /* on_key_pressed (GtkWidget *self, */
234 /* GdkEventKey *event, */
235 /* gpointer user_data); */
237 /* list my signals */
244 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
245 struct _ModestMsgEditWindowPrivate {
248 GtkWidget *header_box;
250 ModestPairList *from_field_protos;
251 GtkWidget *from_field;
252 gchar *original_account_name;
256 GtkWidget *bcc_field;
257 GtkWidget *subject_field;
258 GtkWidget *attachments_view;
259 GtkWidget *priority_icon;
260 GtkWidget *add_attachment_button;
262 GtkWidget *cc_caption;
263 GtkWidget *bcc_caption;
264 gboolean update_caption_visibility;
265 GtkWidget *attachments_caption;
267 GtkTextBuffer *text_buffer;
269 GtkWidget *font_size_toolitem;
270 GtkWidget *font_face_toolitem;
271 GtkWidget *font_color_button;
272 GtkWidget *font_color_toolitem;
273 GSList *font_items_group;
274 GtkWidget *font_tool_button_label;
275 GSList *size_items_group;
276 GtkWidget *size_tool_button_label;
278 GtkWidget *find_toolbar;
281 GtkWidget *font_dialog;
284 guint scroll_drag_timeout_id;
288 TnyList *attachments;
293 TnyHeaderFlags priority_flags;
295 gboolean can_undo, can_redo;
296 gulong clipboard_change_handler_id;
297 gulong default_clipboard_change_handler_id;
298 gulong account_removed_handler_id;
299 guint clipboard_owner_idle;
300 gchar *clipboard_text;
309 GtkWidget *cc_button;
310 GtkWidget *bcc_button;
311 GtkWidget *find_toolbar_button;
314 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
315 MODEST_TYPE_MSG_EDIT_WINDOW, \
316 ModestMsgEditWindowPrivate))
318 static GtkWindowClass *parent_class = NULL;
320 /* uncomment the following if you have defined any signals */
321 /* static guint signals[LAST_SIGNAL] = {0}; */
324 modest_msg_edit_window_get_type (void)
326 static GType my_type = 0;
328 static const GTypeInfo my_info = {
329 sizeof(ModestMsgEditWindowClass),
330 NULL, /* base init */
331 NULL, /* base finalize */
332 (GClassInitFunc) modest_msg_edit_window_class_init,
333 NULL, /* class finalize */
334 NULL, /* class data */
335 sizeof(ModestMsgEditWindow),
337 (GInstanceInitFunc) modest_msg_edit_window_init,
340 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
341 "ModestMsgEditWindow",
349 save_state (ModestWindow *self)
351 modest_widget_memory_save (modest_runtime_get_conf(),
352 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
357 restore_settings (ModestMsgEditWindow *self)
359 ModestConf *conf = NULL;
361 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
363 conf = modest_runtime_get_conf ();
365 /* Dim at start clipboard actions */
366 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
367 gtk_action_set_sensitive (action, FALSE);
368 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
369 gtk_action_set_sensitive (action, FALSE);
370 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
371 gtk_action_set_sensitive (action, FALSE);
373 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
378 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
380 GObjectClass *gobject_class;
381 ModestWindowClass *modest_window_class;
382 HildonWindowClass *hildon_window_class = (HildonWindowClass *) klass;
383 gobject_class = (GObjectClass*) klass;
384 modest_window_class = (ModestWindowClass*) klass;
386 parent_class = g_type_class_peek_parent (klass);
387 gobject_class->finalize = modest_msg_edit_window_finalize;
389 hildon_window_class->toggle_menu = modest_msg_edit_window_toggle_menu;
391 modest_window_class->set_zoom_func = set_zoom_do_nothing;
392 modest_window_class->get_zoom_func = get_zoom_do_nothing;
393 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
394 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
395 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
396 modest_window_class->save_state_func = save_state;
397 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
399 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
403 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
405 ModestMsgEditWindowPrivate *priv;
406 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
408 priv->msg_body = NULL;
410 priv->from_field = NULL;
411 priv->to_field = NULL;
412 priv->cc_field = NULL;
413 priv->bcc_field = NULL;
414 priv->subject_field = NULL;
415 priv->attachments = TNY_LIST (tny_simple_list_new ());
416 priv->images = TNY_LIST (tny_simple_list_new ());
417 priv->images_size = 0;
418 priv->images_count = 0;
421 priv->cc_caption = NULL;
422 priv->bcc_caption = NULL;
423 priv->update_caption_visibility = FALSE;
425 priv->priority_flags = 0;
427 priv->find_toolbar = NULL;
428 priv->last_search = NULL;
430 priv->draft_msg = NULL;
431 priv->outbox_msg = NULL;
432 priv->msg_uid = NULL;
434 priv->can_undo = FALSE;
435 priv->can_redo = FALSE;
436 priv->clipboard_change_handler_id = 0;
437 priv->default_clipboard_change_handler_id = 0;
438 priv->account_removed_handler_id = 0;
439 priv->clipboard_owner_idle = 0;
440 priv->clipboard_text = NULL;
443 priv->scroll_drag_timeout_id = 0;
444 priv->last_upper = 0.0;
446 priv->font_dialog = NULL;
447 priv->app_menu = NULL;
449 if (!is_wp_text_buffer_started) {
450 is_wp_text_buffer_started = TRUE;
451 wp_text_buffer_library_init ();
456 hildon_program_add_window (hildon_program_get_instance(),
462 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
464 static ModestPairList*
465 get_transports (void)
467 GSList *transports = NULL;
469 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
470 GSList *accounts = modest_account_mgr_account_names (account_mgr,
471 TRUE /* only enabled accounts. */);
473 GSList *cursor = accounts;
475 gchar *account_name = cursor->data;
476 gchar *from_string = NULL;
478 from_string = modest_account_mgr_get_from_string (account_mgr,
482 if (from_string && account_name) {
483 gchar *name = account_name;
484 ModestPair *pair = modest_pair_new ((gpointer) name,
485 (gpointer) from_string , TRUE);
486 transports = g_slist_prepend (transports, pair);
489 cursor = cursor->next;
491 g_slist_free (accounts); /* only free the accounts, not the elements,
492 * because they are used in the pairlist */
496 static void window_focus (GtkWindow *window,
500 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
504 scroll_drag_timeout (gpointer userdata)
506 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
507 ModestMsgEditWindowPrivate *priv;
509 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
511 correct_scroll_without_drag_check (win, TRUE);
513 priv->scroll_drag_timeout_id = 0;
519 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
521 ModestMsgEditWindowPrivate *priv;
524 GdkRectangle rectangle;
528 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
530 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
533 insert = gtk_text_buffer_get_insert (priv->text_buffer);
534 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
536 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
537 offset = priv->msg_body->allocation.y;
539 new_value = (offset + rectangle.y);
541 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (priv->pannable), -1, new_value);
545 correct_scroll (ModestMsgEditWindow *w)
547 ModestMsgEditWindowPrivate *priv;
549 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
550 if (gtk_grab_get_current () == priv->msg_body) {
551 if (priv->scroll_drag_timeout_id == 0) {
552 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
558 correct_scroll_without_drag_check (w, TRUE);
562 text_buffer_end_user_action (GtkTextBuffer *buffer,
563 ModestMsgEditWindow *userdata)
566 correct_scroll (userdata);
570 text_buffer_mark_set (GtkTextBuffer *buffer,
573 ModestMsgEditWindow *userdata)
575 gtk_text_buffer_begin_user_action (buffer);
576 gtk_text_buffer_end_user_action (buffer);
580 cut_clipboard_check (GtkTextView *text_view,
583 GtkTextBuffer *buffer;
585 buffer = gtk_text_view_get_buffer (text_view);
586 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
587 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
592 copy_clipboard_check (GtkTextView *text_view,
595 GtkTextBuffer *buffer;
597 buffer = gtk_text_view_get_buffer (text_view);
598 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
599 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
604 attachment_deleted (ModestAttachmentsView *attachments_view,
607 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
612 connect_signals (ModestMsgEditWindow *obj)
614 ModestMsgEditWindowPrivate *priv;
616 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
618 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
619 G_CALLBACK (text_buffer_refresh_attributes), obj);
620 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
621 G_CALLBACK (text_buffer_can_undo), obj);
622 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
623 G_CALLBACK (text_buffer_can_redo), obj);
624 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
625 G_CALLBACK (body_changed), obj);
626 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
627 G_CALLBACK (body_changed), obj);
628 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
629 G_CALLBACK (text_buffer_end_user_action), obj);
630 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
631 G_CALLBACK (text_buffer_mark_set), obj);
632 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
633 G_CALLBACK (text_buffer_apply_tag), obj);
634 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
635 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
636 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
637 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
638 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
639 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
641 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
642 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
644 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
645 G_CALLBACK (msg_body_focus), obj);
646 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
647 G_CALLBACK (msg_body_focus), obj);
648 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
649 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
650 "changed", G_CALLBACK (recpt_field_changed), obj);
651 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
652 "changed", G_CALLBACK (recpt_field_changed), obj);
653 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
654 "changed", G_CALLBACK (recpt_field_changed), obj);
655 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
656 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
657 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
659 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
660 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
662 priv->clipboard_change_handler_id =
663 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
664 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
665 priv->default_clipboard_change_handler_id =
666 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
667 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
669 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
670 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
671 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
675 init_wp_text_view_style ()
677 static gboolean initialized = FALSE;
680 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
686 init_window (ModestMsgEditWindow *obj)
688 GtkWidget *to_caption, *subject_caption;
689 GtkWidget *main_vbox;
690 ModestMsgEditWindowPrivate *priv;
691 GtkActionGroup *action_group;
692 ModestWindowPrivate *parent_priv;
693 GdkPixbuf *window_icon = NULL;
694 GError *error = NULL;
696 GtkSizeGroup *title_size_group;
697 GtkSizeGroup *value_size_group;
698 GtkWidget *subject_box;
699 GtkWidget *attachment_icon;
700 GtkWidget *window_box;
701 #if (GTK_MINOR_VERSION >= 10)
702 GdkAtom deserialize_type;
705 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
706 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
708 parent_priv->ui_manager = gtk_ui_manager_new();
709 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
710 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
712 /* Add common actions */
713 gtk_action_group_add_actions (action_group,
714 modest_msg_edit_action_entries,
715 G_N_ELEMENTS (modest_msg_edit_action_entries),
717 gtk_action_group_add_actions (action_group,
718 hildon2_msg_edit_action_entries,
719 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
721 gtk_action_group_add_toggle_actions (action_group,
722 modest_msg_edit_toggle_action_entries,
723 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
725 gtk_action_group_add_radio_actions (action_group,
726 modest_msg_edit_alignment_radio_action_entries,
727 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
729 G_CALLBACK (modest_ui_actions_on_change_justify),
731 gtk_action_group_add_radio_actions (action_group,
732 modest_msg_edit_priority_action_entries,
733 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
735 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
737 gtk_action_group_add_radio_actions (action_group,
738 modest_msg_edit_file_format_action_entries,
739 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
740 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
741 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
743 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
744 g_object_unref (action_group);
746 /* Load the UI definition */
747 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
750 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
751 g_clear_error (&error);
754 /* Add accelerators */
755 gtk_window_add_accel_group (GTK_WINDOW (obj),
756 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
758 parent_priv->menubar = NULL;
760 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
761 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
763 /* Note: This ModestPairList* must exist for as long as the picker
764 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
765 * so it can't know how to manage its memory. */
766 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
767 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
769 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
770 _("mail_va_from"), priv->from_field);
772 priv->to_field = modest_recpt_editor_new ();
773 priv->cc_field = modest_recpt_editor_new ();
774 priv->bcc_field = modest_recpt_editor_new ();
775 subject_box = gtk_hbox_new (FALSE, 0);
776 priv->priority_icon = gtk_image_new ();
777 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
778 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
779 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
780 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
781 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
782 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
783 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
784 priv->add_attachment_button = gtk_button_new ();
785 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
786 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
787 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
788 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 0.5);
789 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
790 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
791 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
792 priv->attachments_view = modest_attachments_view_new (NULL);
794 priv->header_box = gtk_vbox_new (FALSE, 0);
796 to_caption = modest_maemo_utils_create_captioned_with_size_type
797 (title_size_group, value_size_group,
798 _("mail_va_to"), priv->to_field,
799 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
800 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
801 (title_size_group, value_size_group,
802 _("mail_va_cc"), priv->cc_field,
803 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
804 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
805 (title_size_group, value_size_group,
806 _("mail_va_hotfix1"), priv->bcc_field,
807 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
808 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
809 _("mail_va_subject"), subject_box);
810 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
811 _("mail_va_attachment"),
812 priv->attachments_view,
813 HILDON_SIZE_AUTO_WIDTH |
814 HILDON_SIZE_AUTO_HEIGHT);
815 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
816 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
817 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
818 g_object_unref (title_size_group);
819 g_object_unref (value_size_group);
821 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
822 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
823 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
824 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
825 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
826 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
827 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
829 init_wp_text_view_style ();
831 priv->msg_body = wp_text_view_new ();
834 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
835 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
836 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
837 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
838 #if (GTK_MINOR_VERSION >= 10)
839 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
840 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
842 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
843 deserialize_type, TRUE);
845 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
847 priv->find_toolbar = hildon_find_toolbar_new (NULL);
848 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
850 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
852 priv->pannable = hildon_pannable_area_new ();
854 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
856 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
857 priv->frame = gtk_frame_new (NULL);
858 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
860 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), main_vbox);
861 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
863 window_box = gtk_vbox_new (FALSE, 0);
864 gtk_container_add (GTK_CONTAINER(obj), window_box);
866 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
868 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
870 /* Set window icon */
871 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
873 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
874 g_object_unref (window_icon);
879 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
881 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
883 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
884 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
885 priv->clipboard_change_handler_id))
886 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
887 priv->clipboard_change_handler_id);
888 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
889 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
890 priv->default_clipboard_change_handler_id))
891 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
892 priv->default_clipboard_change_handler_id);
894 if (priv->account_removed_handler_id &&
895 g_signal_handler_is_connected (modest_runtime_get_account_store (),
896 priv->account_removed_handler_id))
897 g_signal_handler_disconnect(modest_runtime_get_account_store (),
898 priv->account_removed_handler_id);
902 modest_msg_edit_window_finalize (GObject *obj)
904 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
906 /* Sanity check: shouldn't be needed, the window mgr should
907 call this function before */
908 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
910 if (priv->font_dialog != NULL) {
911 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
914 if (priv->clipboard_text != NULL) {
915 g_free (priv->clipboard_text);
916 priv->clipboard_text = NULL;
919 if (priv->draft_msg != NULL) {
920 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
921 if (TNY_IS_HEADER (header)) {
922 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
923 modest_window_mgr_unregister_header (mgr, header);
925 g_object_unref (priv->draft_msg);
926 priv->draft_msg = NULL;
928 if (priv->outbox_msg != NULL) {
929 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
930 if (TNY_IS_HEADER (header)) {
931 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
932 modest_window_mgr_unregister_header (mgr, header);
934 g_object_unref (priv->outbox_msg);
935 priv->outbox_msg = NULL;
937 if (priv->scroll_drag_timeout_id > 0) {
938 g_source_remove (priv->scroll_drag_timeout_id);
939 priv->scroll_drag_timeout_id = 0;
941 if (priv->clipboard_owner_idle > 0) {
942 g_source_remove (priv->clipboard_owner_idle);
943 priv->clipboard_owner_idle = 0;
945 if (priv->original_account_name)
946 g_free (priv->original_account_name);
947 g_free (priv->msg_uid);
948 g_free (priv->last_search);
949 g_slist_free (priv->font_items_group);
950 g_slist_free (priv->size_items_group);
951 g_object_unref (priv->attachments);
952 g_object_unref (priv->images);
954 /* This had to stay alive for as long as the picker that used it: */
955 modest_pair_list_free (priv->from_field_protos);
957 G_OBJECT_CLASS(parent_class)->finalize (obj);
961 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
963 GdkPixbufLoader *loader;
969 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
971 if (loader == NULL) {
977 tny_stream_reset (TNY_STREAM (stream));
978 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
979 GError *error = NULL;
980 unsigned char read_buffer[128];
982 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
984 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
986 g_error_free (error);
991 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
993 g_object_ref (pixbuf);
994 gdk_pixbuf_loader_close (loader, NULL);
995 g_object_unref (loader);
1000 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1001 GdkPixbuf *new_pixbuf;
1003 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1004 gdk_pixbuf_get_width (pixbuf);
1005 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1006 g_object_unref (pixbuf);
1007 pixbuf = new_pixbuf;
1011 *stream_size = size;
1017 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1019 ModestMsgEditWindowPrivate *priv;
1022 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1024 for (iter = tny_list_create_iterator (attachments);
1025 !tny_iterator_is_done (iter);
1026 tny_iterator_next (iter)) {
1027 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1028 const gchar *cid = tny_mime_part_get_content_id (part);
1029 const gchar *mime_type = tny_mime_part_get_content_type (part);
1030 if ((cid != NULL)&&(mime_type != NULL)) {
1031 guint64 stream_size;
1032 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1033 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1036 g_object_unref (stream);
1038 if (pixbuf != NULL) {
1039 priv->images_count ++;
1040 priv->images_size += stream_size;
1041 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1042 g_object_unref (pixbuf);
1045 g_object_unref (part);
1047 g_object_unref (iter);
1051 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1053 TnyMimePart *parent = NULL;
1054 const gchar *content_type = NULL;
1055 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1057 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1059 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1060 parent = g_object_ref (msg);
1061 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1062 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1065 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1066 iter = tny_list_create_iterator (parts);
1067 while (!tny_iterator_is_done (iter)) {
1069 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1070 content_type = tny_mime_part_get_content_type (part);
1071 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1075 g_object_unref (part);
1077 tny_iterator_next (iter);
1079 g_object_unref (iter);
1080 g_object_unref (parts);
1083 if (parent != NULL) {
1084 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1087 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1088 iter = tny_list_create_iterator (parts);
1089 while (!tny_iterator_is_done (iter)) {
1091 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1092 content_type = tny_mime_part_get_content_type (part);
1093 if (content_type && g_str_has_prefix (content_type, "image/")) {
1094 tny_list_prepend (priv->images, (GObject *) part);
1096 g_object_unref (part);
1097 tny_iterator_next (iter);
1099 g_object_unref (iter);
1100 g_object_unref (parts);
1101 g_object_unref (parent);
1106 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1109 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1111 for (iter = tny_list_create_iterator (attachments) ;
1112 !tny_iterator_is_done (iter);
1113 tny_iterator_next (iter)) {
1114 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1115 const gchar *cid = tny_mime_part_get_content_id (part);
1117 char *invalid = NULL;
1118 gint int_cid = strtol (cid, &invalid, 10);
1119 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1120 priv->next_cid = int_cid + 1;
1123 g_object_unref (part);
1125 g_object_unref (iter);
1129 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1132 gchar *to, *cc, *bcc, *subject;
1134 ModestMsgEditWindowPrivate *priv;
1135 ModestWindowPrivate *parent_priv;
1137 TnyHeaderFlags priority_flags;
1138 TnyFolder *msg_folder;
1139 gboolean is_html = FALSE;
1140 gboolean field_view_set;
1142 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1143 g_return_if_fail (TNY_IS_MSG (msg));
1145 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1146 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1148 header = tny_msg_get_header (msg);
1149 to = tny_header_dup_to (header);
1150 cc = tny_header_dup_cc (header);
1151 bcc = tny_header_dup_bcc (header);
1152 subject = tny_header_dup_subject (header);
1153 priority_flags = tny_header_get_priority (header);
1156 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1158 field_view_set = TRUE;
1160 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1161 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1162 gtk_widget_show (priv->cc_caption);
1163 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1164 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1165 gtk_widget_hide (priv->cc_caption);
1166 field_view_set = FALSE;
1168 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1170 field_view_set = TRUE;
1172 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1173 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1174 gtk_widget_show (priv->bcc_caption);
1175 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1176 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1177 gtk_widget_hide (priv->bcc_caption);
1178 field_view_set = FALSE;
1180 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1184 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1185 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1188 update_window_title (self);
1190 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1191 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1193 if ((body == NULL)||(body[0] == '\0')) {
1195 body = modest_text_utils_convert_to_html ("");
1198 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1199 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1202 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1205 /* Add attachments to the view */
1206 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1207 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1208 if (tny_list_get_length (priv->attachments) == 0) {
1209 gtk_widget_hide (priv->attachments_caption);
1211 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1212 gtk_widget_show_all (priv->attachments_caption);
1214 get_related_images (self, msg);
1215 update_next_cid (self, priv->attachments);
1216 update_next_cid (self, priv->images);
1217 replace_with_images (self, priv->images);
1219 if (preserve_is_rich && !is_html) {
1220 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1221 /* Get the default format required from configuration */
1222 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1223 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1226 /* Set the default focus depending on having already a To: field or not */
1227 if ((!to)||(*to == '\0')) {
1228 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1230 gtk_widget_grab_focus (priv->msg_body);
1233 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1235 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1236 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1238 modest_msg_edit_window_set_modified (self, FALSE);
1240 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1241 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1242 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1243 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1245 if (priv->msg_uid) {
1246 g_free (priv->msg_uid);
1247 priv->msg_uid = NULL;
1250 /* we should set a reference to the incoming message if it is a draft */
1251 msg_folder = tny_msg_get_folder (msg);
1253 if (modest_tny_folder_is_local_folder (msg_folder)) {
1254 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1255 if (type == TNY_FOLDER_TYPE_INVALID)
1256 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1258 if (type == TNY_FOLDER_TYPE_DRAFTS)
1259 priv->draft_msg = g_object_ref(msg);
1260 if (type == TNY_FOLDER_TYPE_OUTBOX)
1261 priv->outbox_msg = g_object_ref(msg);
1262 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1264 g_object_unref (msg_folder);
1274 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1277 GList *item_children, *node;
1278 GtkWidget *bin_child;
1280 bin_child = gtk_bin_get_child (GTK_BIN(item));
1282 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1284 for (node = item_children; node != NULL; node = g_list_next (node)) {
1285 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1286 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1289 g_list_free (item_children);
1293 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1296 GList *item_children, *node;
1298 box = gtk_bin_get_child (GTK_BIN (item));
1299 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1300 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1302 for (node = item_children; node != NULL; node = g_list_next (node)) {
1303 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1304 if (GTK_IS_TOGGLE_BUTTON (node->data))
1305 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1306 else if (GTK_IS_BUTTON (node->data))
1307 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1309 g_list_free (item_children);
1314 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1316 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1317 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1318 GtkWidget *placeholder;
1319 GtkWidget *tool_item;
1324 GtkWidget *sizes_menu;
1325 GtkWidget *fonts_menu;
1326 GSList *radio_group = NULL;
1327 GSList *node = NULL;
1331 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1332 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1334 /* Font color placeholder */
1335 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1336 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1339 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1340 priv->font_color_button = hildon_color_button_new ();
1341 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1342 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1343 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1344 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1345 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1346 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1347 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1349 G_CALLBACK (modest_msg_edit_window_color_button_change),
1352 /* Font size and face placeholder */
1353 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1354 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1356 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1357 priv->size_tool_button_label = gtk_label_new (NULL);
1358 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1359 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1360 size_text,"</span>", NULL);
1361 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1363 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1364 sizes_menu = gtk_menu_new ();
1365 priv->size_items_group = NULL;
1367 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1368 GtkWidget *size_menu_item;
1370 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1371 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1372 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1373 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1374 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1375 gtk_widget_show (size_menu_item);
1377 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1381 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1382 GtkWidget *item = (GtkWidget *) node->data;
1383 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1387 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1388 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1389 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1390 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1391 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1392 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1393 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1394 priv->font_size_toolitem = tool_item;
1397 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1398 priv->font_tool_button_label = gtk_label_new (NULL);
1399 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1400 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1402 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1403 fonts_menu = gtk_menu_new ();
1404 priv->font_items_group = NULL;
1406 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1407 GtkWidget *font_menu_item;
1408 GtkWidget *child_label;
1410 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1411 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1412 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1413 wp_get_font_name (font_index), "</span>", NULL);
1414 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1417 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1418 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1419 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1420 gtk_widget_show (font_menu_item);
1422 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1425 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1426 GtkWidget *item = (GtkWidget *) node->data;
1427 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1430 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1431 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1432 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1433 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1434 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1435 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1436 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1437 priv->font_face_toolitem = tool_item;
1439 /* Set expand and homogeneous for remaining items */
1440 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1441 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1442 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1443 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1444 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1445 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1446 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1447 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1448 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1450 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1451 will not show the tool items added to the placeholders) */
1452 gtk_widget_show_all (parent_priv->toolbar);
1454 /* Set the no show all *after* showing all items. We do not
1455 want the toolbar to be shown with a show all because it
1456 could go agains the gconf setting regarding showing or not
1457 the toolbar of the editor window */
1458 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1464 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1467 ModestWindowPrivate *parent_priv;
1468 ModestMsgEditWindowPrivate *priv;
1469 ModestDimmingRulesGroup *menu_rules_group = NULL;
1470 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1471 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1472 ModestWindowMgr *mgr = NULL;
1474 g_return_val_if_fail (msg, NULL);
1475 g_return_val_if_fail (account_name, NULL);
1477 mgr = modest_runtime_get_window_mgr ();
1479 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1481 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1482 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1484 /* Menubar. Update the state of some toggles */
1485 priv->from_field_protos = get_transports ();
1486 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1487 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1488 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1490 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1491 hildon_touch_selector_get_current_text
1492 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1493 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1494 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1497 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1499 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1501 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1503 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1505 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1506 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1507 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1508 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1509 /* Add common dimming rules */
1510 modest_dimming_rules_group_add_rules (menu_rules_group,
1511 modest_msg_edit_window_menu_dimming_entries,
1512 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1513 MODEST_WINDOW (obj));
1514 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1515 modest_msg_edit_window_toolbar_dimming_entries,
1516 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1517 MODEST_WINDOW (obj));
1518 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1519 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1520 MODEST_WINDOW (obj));
1521 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1522 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1523 MODEST_WINDOW (obj));
1524 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1525 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1526 MODEST_WINDOW (obj));
1527 /* Insert dimming rules group for this window */
1528 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1529 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1530 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1532 /* Setup app menu */
1533 setup_menu (MODEST_MSG_EDIT_WINDOW (obj), menu_rules_group);
1535 /* Checks the dimming rules */
1536 g_object_unref (menu_rules_group);
1537 g_object_unref (toolbar_rules_group);
1538 g_object_unref (clipboard_rules_group);
1539 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1541 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1543 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1544 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1545 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1546 priv->update_caption_visibility = TRUE;
1548 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1550 /* Track account-removed signal, this window should be closed
1551 in the case we're creating a mail associated to the account
1553 priv->account_removed_handler_id =
1554 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1556 G_CALLBACK(on_account_removed),
1559 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1561 return (ModestWindow*) obj;
1565 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1567 GString **string_buffer = (GString **) user_data;
1569 *string_buffer = g_string_append (*string_buffer, buffer);
1575 * @result: A new string which should be freed with g_free().
1578 get_formatted_data (ModestMsgEditWindow *edit_window)
1580 ModestMsgEditWindowPrivate *priv;
1581 GString *string_buffer = g_string_new ("");
1583 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1585 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1587 modest_text_utils_hyperlinkify (string_buffer);
1589 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1591 return g_string_free (string_buffer, FALSE);
1596 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1599 const gchar *account_name;
1600 ModestMsgEditWindowPrivate *priv;
1601 TnyIterator *att_iter;
1603 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1605 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1607 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1608 g_return_val_if_fail (account_name, NULL);
1611 /* don't free these (except from) */
1612 data = g_slice_new0 (MsgData);
1613 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1615 data->account_name = g_strdup (account_name);
1616 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1617 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1618 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1619 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1620 if (priv->draft_msg) {
1621 data->draft_msg = g_object_ref (priv->draft_msg);
1622 } else if (priv->outbox_msg) {
1623 data->draft_msg = g_object_ref (priv->outbox_msg);
1625 data->draft_msg = NULL;
1628 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1630 gtk_text_buffer_get_bounds (buf, &b, &e);
1631 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1633 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1634 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1636 data->html_body = NULL;
1638 /* deep-copy the data */
1639 att_iter = tny_list_create_iterator (priv->attachments);
1640 data->attachments = NULL;
1641 while (!tny_iterator_is_done (att_iter)) {
1642 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1643 if (!(TNY_IS_MIME_PART(part))) {
1644 g_warning ("strange data in attachment list");
1645 g_object_unref (part);
1646 tny_iterator_next (att_iter);
1649 data->attachments = g_list_append (data->attachments,
1651 tny_iterator_next (att_iter);
1653 g_object_unref (att_iter);
1655 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1656 att_iter = tny_list_create_iterator (priv->images);
1657 data->images = NULL;
1658 while (!tny_iterator_is_done (att_iter)) {
1659 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1661 if (!(TNY_IS_MIME_PART(part))) {
1662 g_warning ("strange data in attachment list");
1663 g_object_unref (part);
1664 tny_iterator_next (att_iter);
1667 cid = tny_mime_part_get_content_id (part);
1669 gchar *image_tag_id;
1670 GtkTextTag *image_tag;
1672 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1673 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1674 g_free (image_tag_id);
1676 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1678 ((gtk_text_iter_has_tag (&iter, image_tag))||
1679 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1680 data->images = g_list_append (data->images,
1681 g_object_ref (part));
1683 g_object_unref (part);
1684 tny_iterator_next (att_iter);
1686 g_object_unref (att_iter);
1688 data->priority_flags = priv->priority_flags;
1695 unref_gobject (GObject *obj, gpointer data)
1697 if (!G_IS_OBJECT(obj))
1699 g_object_unref (obj);
1703 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1706 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1714 g_free (data->from);
1715 g_free (data->subject);
1716 g_free (data->plain_body);
1717 g_free (data->html_body);
1718 g_free (data->account_name);
1720 if (data->draft_msg != NULL) {
1721 g_object_unref (data->draft_msg);
1722 data->draft_msg = NULL;
1725 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1726 g_list_free (data->attachments);
1727 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1728 g_list_free (data->images);
1730 g_slice_free (MsgData, data);
1734 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1736 guint64 *parts_size)
1738 ModestMsgEditWindowPrivate *priv;
1740 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1742 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1744 /* TODO: add images */
1745 *parts_size += priv->images_size;
1746 *parts_count += priv->images_count;
1751 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1754 ModestMsgEditWindowPrivate *priv = NULL;
1755 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1757 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1759 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1761 return MODEST_MSG_EDIT_FORMAT_HTML;
1763 return MODEST_MSG_EDIT_FORMAT_TEXT;
1767 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1768 ModestMsgEditFormat format)
1770 ModestMsgEditWindowPrivate *priv;
1772 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1773 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1776 case MODEST_MSG_EDIT_FORMAT_HTML:
1777 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1779 case MODEST_MSG_EDIT_FORMAT_TEXT:
1780 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1783 g_return_if_reached ();
1787 ModestMsgEditFormatState *
1788 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1790 ModestMsgEditFormatState *format_state = NULL;
1791 ModestMsgEditWindowPrivate *priv;
1792 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1794 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1795 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1797 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1799 format_state = g_new0 (ModestMsgEditFormatState, 1);
1800 format_state->bold = buffer_format->bold&0x1;
1801 format_state->italics = buffer_format->italic&0x1;
1802 format_state->bullet = buffer_format->bullet&0x1;
1803 format_state->color = buffer_format->color;
1804 format_state->font_size = buffer_format->font_size;
1805 format_state->font_family = wp_get_font_name (buffer_format->font);
1806 format_state->justification = buffer_format->justification;
1807 g_free (buffer_format);
1809 return format_state;
1814 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1815 const ModestMsgEditFormatState *format_state)
1817 ModestMsgEditWindowPrivate *priv;
1818 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1819 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1820 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1821 g_return_if_fail (format_state != NULL);
1823 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1824 gtk_widget_grab_focus (priv->msg_body);
1825 buffer_format->bold = (format_state->bold != FALSE);
1826 buffer_format->italic = (format_state->italics != FALSE);
1827 buffer_format->color = format_state->color;
1828 buffer_format->font_size = format_state->font_size;
1829 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1830 buffer_format->justification = format_state->justification;
1831 buffer_format->bullet = format_state->bullet;
1833 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1835 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1836 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1837 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1838 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1839 buffer_format->cs.font = (buffer_format->font != current_format->font);
1840 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1841 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1843 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1844 if (buffer_format->cs.bold) {
1845 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1846 GINT_TO_POINTER (buffer_format->bold&0x1));
1848 if (buffer_format->cs.italic) {
1849 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1850 GINT_TO_POINTER (buffer_format->italic&0x1));
1852 if (buffer_format->cs.color) {
1853 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1854 GINT_TO_POINTER (&(buffer_format->color)));
1856 if (buffer_format->cs.font_size) {
1857 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1858 GINT_TO_POINTER (buffer_format->font_size));
1860 if (buffer_format->cs.justification) {
1861 switch (buffer_format->justification) {
1862 case GTK_JUSTIFY_LEFT:
1863 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1864 GINT_TO_POINTER(TRUE));
1866 case GTK_JUSTIFY_CENTER:
1867 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1868 GINT_TO_POINTER(TRUE));
1870 case GTK_JUSTIFY_RIGHT:
1871 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1872 GINT_TO_POINTER(TRUE));
1879 if (buffer_format->cs.font) {
1880 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1881 GINT_TO_POINTER (buffer_format->font));
1883 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1884 if (buffer_format->cs.bullet) {
1885 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1886 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1888 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1890 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1892 g_free (buffer_format);
1893 g_free (current_format);
1895 /* Check dimming rules */
1896 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1897 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1901 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1903 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1905 ModestWindowPrivate *parent_priv;
1906 ModestMsgEditWindowPrivate *priv;
1907 GtkWidget *new_size_menuitem;
1908 GtkWidget *new_font_menuitem;
1910 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1911 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1913 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1914 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1915 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1916 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1918 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1919 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1920 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1923 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1925 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1926 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1928 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1929 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1931 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1932 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1935 switch (buffer_format->justification)
1937 case GTK_JUSTIFY_LEFT:
1938 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1940 case GTK_JUSTIFY_CENTER:
1941 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1943 case GTK_JUSTIFY_RIGHT:
1944 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1951 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1953 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1954 G_CALLBACK (modest_msg_edit_window_color_button_change),
1956 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1957 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1958 G_CALLBACK (modest_msg_edit_window_color_button_change),
1961 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1962 buffer_format->font_size))->data);
1963 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1967 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1968 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1969 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1971 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1972 G_CALLBACK (modest_msg_edit_window_size_change),
1974 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1975 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1976 G_CALLBACK (modest_msg_edit_window_size_change),
1980 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1981 buffer_format->font))->data);
1982 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1986 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1987 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1988 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1990 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1991 G_CALLBACK (modest_msg_edit_window_font_change),
1993 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1994 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1995 G_CALLBACK (modest_msg_edit_window_font_change),
1999 g_free (buffer_format);
2003 #ifdef MODEST_HILDON_VERSION_0
2005 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2008 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2009 ModestMsgEditWindowPrivate *priv;
2010 GtkWidget *dialog = NULL;
2012 GdkColor *new_color = NULL;
2014 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2015 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2017 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2018 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2019 g_free (buffer_format);
2021 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2022 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2023 if (new_color != NULL) {
2024 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2025 (gpointer) new_color);
2028 gtk_widget_destroy (dialog);
2033 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2036 ModestMsgEditWindowPrivate *priv;
2037 GtkWidget *dialog = NULL;
2039 GdkColor *old_color = NULL;
2040 const GdkColor *new_color = NULL;
2042 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2043 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2045 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2046 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2048 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2049 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2050 if (new_color != NULL)
2051 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2053 gtk_widget_destroy (dialog);
2059 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2062 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2063 ModestMsgEditWindowPrivate *priv;
2064 GtkWidget *dialog = NULL;
2066 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2067 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2069 dialog = hildon_color_chooser_new ();
2070 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2071 g_free (buffer_format);
2073 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2075 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2076 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2079 gtk_widget_destroy (dialog);
2084 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2087 ModestMsgEditWindowPrivate *priv;
2088 GtkWidget *dialog = NULL;
2089 GdkColor *old_color = NULL;
2091 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2092 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2094 dialog = hildon_color_chooser_new ();
2095 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2097 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2099 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2100 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2102 gtk_widget_destroy (dialog);
2105 #endif /*!MODEST_HILDON_VERSION_0*/
2110 create_stream_for_uri (const gchar* uri)
2115 TnyStream *result = NULL;
2117 GnomeVFSHandle *handle = NULL;
2118 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2119 if (test == GNOME_VFS_OK) {
2120 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2121 /* Streams over OBEX (Bluetooth) are not seekable but
2122 * we expect them to be (we might need to read them
2123 * several times). So if this is a Bluetooth URI just
2124 * read the whole file into memory (this is not a fast
2125 * protocol so we can assume that these files are not
2126 * going to be very big) */
2127 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2128 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2129 TnyStream *memstream = tny_camel_mem_stream_new ();
2130 tny_stream_write_to_stream (vfssstream, memstream);
2131 g_object_unref (vfssstream);
2134 result = vfssstream;
2142 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2145 ModestMsgEditWindowPrivate *priv;
2146 GtkWidget *dialog = NULL;
2148 GSList *uris = NULL;
2149 GSList *uri_node = NULL;
2151 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2153 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2154 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2155 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2157 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2159 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2160 GTK_WINDOW (dialog), GTK_WINDOW (window));
2162 response = gtk_dialog_run (GTK_DIALOG (dialog));
2164 case GTK_RESPONSE_OK:
2165 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2170 gtk_widget_destroy (dialog);
2172 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2174 GnomeVFSHandle *handle = NULL;
2175 GnomeVFSResult result;
2176 GtkTextIter position;
2177 GtkTextMark *insert_mark;
2179 uri = (const gchar *) uri_node->data;
2180 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2181 if (result == GNOME_VFS_OK) {
2183 GnomeVFSFileInfo *info;
2184 gchar *filename, *basename, *escaped_filename;
2185 TnyMimePart *mime_part;
2187 const gchar *mime_type = NULL;
2188 GnomeVFSURI *vfs_uri;
2189 guint64 stream_size;
2191 gnome_vfs_close (handle);
2192 vfs_uri = gnome_vfs_uri_new (uri);
2194 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2195 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2196 g_free (escaped_filename);
2197 gnome_vfs_uri_unref (vfs_uri);
2198 info = gnome_vfs_file_info_new ();
2200 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2201 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2203 mime_type = gnome_vfs_file_info_get_mime_type (info);
2205 mime_part = tny_platform_factory_new_mime_part
2206 (modest_runtime_get_platform_factory ());
2208 TnyStream *stream = create_stream_for_uri (uri);
2210 if (stream == NULL) {
2212 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2214 g_object_unref (mime_part);
2215 gnome_vfs_file_info_unref (info);
2219 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2221 content_id = g_strdup_printf ("%d", priv->next_cid);
2222 tny_mime_part_set_content_id (mime_part, content_id);
2223 g_free (content_id);
2226 basename = g_path_get_basename (filename);
2227 tny_mime_part_set_filename (mime_part, basename);
2230 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2232 if (pixbuf != NULL) {
2233 priv->images_size += stream_size;
2234 priv->images_count ++;
2235 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2236 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2237 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2238 g_object_unref (pixbuf);
2241 tny_list_prepend (priv->images, (GObject *) mime_part);
2242 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2244 g_object_unref (mime_part);
2245 gnome_vfs_file_info_unref (info);
2254 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2256 GtkWidget *dialog = NULL;
2258 GSList *uris = NULL;
2260 GnomeVFSFileSize total_size, allowed_size;
2261 ModestMsgEditWindowPrivate *priv;
2265 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2267 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2269 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2272 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2273 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2274 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2275 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), GTK_WINDOW (window));
2277 response = gtk_dialog_run (GTK_DIALOG (dialog));
2279 case GTK_RESPONSE_OK:
2280 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2285 gtk_widget_destroy (dialog);
2287 /* allowed size is the maximum size - what's already there */
2288 modest_attachments_view_get_sizes (
2289 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2290 &att_num, &att_size);
2291 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2294 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2296 const gchar *uri = (const gchar *) uri_node->data;
2298 total_size += modest_msg_edit_window_attach_file_one
2299 (window, uri, allowed_size);
2301 if (total_size > allowed_size) {
2302 g_warning ("%s: total size: %u",
2303 __FUNCTION__, (unsigned int)total_size);
2307 allowed_size -= total_size;
2311 g_slist_foreach (uris, (GFunc) g_free, NULL);
2312 g_slist_free (uris);
2317 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2319 GnomeVFSFileSize allowed_size)
2322 GnomeVFSHandle *handle = NULL;
2323 ModestMsgEditWindowPrivate *priv;
2324 GnomeVFSResult result;
2325 GnomeVFSFileSize size = 0;
2326 g_return_val_if_fail (window, 0);
2327 g_return_val_if_fail (uri, 0);
2329 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2331 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2332 if (result == GNOME_VFS_OK) {
2333 TnyMimePart *mime_part;
2335 const gchar *mime_type = NULL;
2337 gchar *escaped_filename;
2340 GnomeVFSFileInfo *info;
2341 GnomeVFSURI *vfs_uri;
2343 gnome_vfs_close (handle);
2344 vfs_uri = gnome_vfs_uri_new (uri);
2347 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2348 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2349 g_free (escaped_filename);
2350 gnome_vfs_uri_unref (vfs_uri);
2352 info = gnome_vfs_file_info_new ();
2354 if (gnome_vfs_get_file_info (uri,
2356 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2358 mime_type = gnome_vfs_file_info_get_mime_type (info);
2359 mime_part = tny_platform_factory_new_mime_part
2360 (modest_runtime_get_platform_factory ());
2362 /* try to get the attachment's size; this may fail for weird
2363 * file systems, like obex, upnp... */
2364 if (allowed_size != 0 &&
2365 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2367 if (size > allowed_size) {
2368 modest_platform_information_banner (NULL, NULL,
2369 dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2373 g_warning ("%s: could not get attachment size", __FUNCTION__);
2375 stream = create_stream_for_uri (uri);
2377 if (stream == NULL) {
2379 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2381 g_object_unref (mime_part);
2382 gnome_vfs_file_info_unref (info);
2386 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2387 g_object_unref (stream);
2389 content_id = g_strdup_printf ("%d", priv->next_cid);
2390 tny_mime_part_set_content_id (mime_part, content_id);
2391 g_free (content_id);
2394 basename = g_path_get_basename (filename);
2395 tny_mime_part_set_filename (mime_part, basename);
2398 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2399 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2401 info->size == 0, info->size);
2402 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2403 gtk_widget_show_all (priv->attachments_caption);
2404 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2406 g_object_unref (mime_part);
2407 gnome_vfs_file_info_unref (info);
2414 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2417 ModestMsgEditWindowPrivate *priv;
2420 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2421 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2423 if (att_list == NULL) {
2424 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2426 g_object_ref (att_list);
2429 if (tny_list_get_length (att_list) == 0) {
2430 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2432 gboolean dialog_response;
2433 gchar *message = NULL;
2434 gchar *filename = NULL;
2436 if (tny_list_get_length (att_list) == 1) {
2438 iter = tny_list_create_iterator (att_list);
2439 part = (TnyMimePart *) tny_iterator_get_current (iter);
2440 g_object_unref (iter);
2441 if (TNY_IS_MSG (part)) {
2442 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2444 filename = tny_header_dup_subject (header);
2445 g_object_unref (header);
2447 if (filename == NULL) {
2448 filename = g_strdup (_("mail_va_no_subject"));
2451 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2453 g_object_unref (part);
2455 filename = g_strdup ("");
2457 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2458 tny_list_get_length (att_list)), filename);
2461 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2464 if (dialog_response != GTK_RESPONSE_OK) {
2465 g_object_unref (att_list);
2468 hildon_banner_show_information (NULL, NULL, _("mcen_me_inbox_remove_attachments"));
2470 for (iter = tny_list_create_iterator (att_list);
2471 !tny_iterator_is_done (iter);
2472 tny_iterator_next (iter)) {
2473 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2474 const gchar *att_id;
2475 tny_list_remove (priv->attachments, (GObject *) mime_part);
2477 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2479 if (tny_list_get_length (priv->attachments) == 0)
2480 gtk_widget_hide (priv->attachments_caption);
2481 att_id = tny_mime_part_get_content_id (mime_part);
2483 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2485 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2486 g_object_unref (mime_part);
2488 g_object_unref (iter);
2491 g_object_unref (att_list);
2493 /* if the last attachment has been removed, focus the Subject: field */
2494 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2495 gtk_widget_grab_focus (priv->subject_field);
2499 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2502 ModestMsgEditWindowPrivate *priv;
2503 GdkColor *new_color;
2504 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2506 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2507 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2510 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2512 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2514 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2516 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2521 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2524 ModestMsgEditWindowPrivate *priv;
2525 gint new_size_index;
2526 ModestMsgEditWindow *window;
2529 window = MODEST_MSG_EDIT_WINDOW (userdata);
2530 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2531 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2533 if (gtk_check_menu_item_get_active (menu_item)) {
2535 WPTextBufferFormat format;
2537 memset (&format, 0, sizeof (format));
2538 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2540 label = gtk_bin_get_child (GTK_BIN (menu_item));
2542 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2543 format.cs.font_size = TRUE;
2544 format.cs.text_position = TRUE;
2545 format.cs.font = TRUE;
2546 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2547 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2549 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2550 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2551 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2553 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2554 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2555 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2561 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2564 ModestMsgEditWindowPrivate *priv;
2565 gint new_font_index;
2566 ModestMsgEditWindow *window;
2569 window = MODEST_MSG_EDIT_WINDOW (userdata);
2570 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2571 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2573 if (gtk_check_menu_item_get_active (menu_item)) {
2576 label = gtk_bin_get_child (GTK_BIN (menu_item));
2578 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2580 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2581 GINT_TO_POINTER(new_font_index)))
2582 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2584 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2585 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2586 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2592 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2595 ModestMsgEditWindowPrivate *priv = NULL;
2596 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2598 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2599 if (!priv->update_caption_visibility)
2602 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2604 gtk_widget_show (priv->cc_caption);
2606 gtk_widget_hide (priv->cc_caption);
2608 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2612 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2615 ModestMsgEditWindowPrivate *priv = NULL;
2616 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2618 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2619 if (!priv->update_caption_visibility)
2622 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2624 gtk_widget_show (priv->bcc_caption);
2626 gtk_widget_hide (priv->bcc_caption);
2628 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2632 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2633 ModestRecptEditor *editor)
2635 ModestMsgEditWindowPrivate *priv;
2637 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2638 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2640 /* we check for low-mem; in that case, show a warning, and don't allow
2641 * for the addressbook
2643 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2646 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2648 if (editor == NULL) {
2649 GtkWidget *view_focus;
2650 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2652 /* This code should be kept in sync with ModestRecptEditor. The
2653 textview inside the recpt editor is the one that really gets the
2654 focus. As it's inside a scrolled window, and this one inside the
2655 hbox recpt editor inherits from, we'll need to go up in the
2656 hierarchy to know if the text view is part of the recpt editor
2657 or if it's a different text entry */
2659 if (gtk_widget_get_parent (view_focus)) {
2660 GtkWidget *first_parent;
2662 first_parent = gtk_widget_get_parent (view_focus);
2663 if (gtk_widget_get_parent (first_parent) &&
2664 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2665 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2670 editor = MODEST_RECPT_EDITOR (priv->to_field);
2674 modest_address_book_select_addresses (editor);
2679 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2681 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2683 modest_msg_edit_window_open_addressbook (window, NULL);
2687 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2688 gboolean show_toolbar)
2690 ModestWindowPrivate *parent_priv;
2692 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2693 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2695 /* We can not just use the code of
2696 modest_msg_edit_window_setup_toolbar because it has a
2697 mixture of both initialization and creation code. */
2699 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2701 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2705 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2706 TnyHeaderFlags priority_flags)
2708 ModestMsgEditWindowPrivate *priv;
2709 ModestWindowPrivate *parent_priv;
2711 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2713 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2714 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2716 if (priv->priority_flags != priority_flags) {
2717 GtkAction *priority_action = NULL;
2719 priv->priority_flags = priority_flags;
2721 switch (priority_flags) {
2722 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2723 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2724 MODEST_HEADER_ICON_HIGH,
2725 HILDON_ICON_SIZE_XSMALL);
2726 gtk_widget_show (priv->priority_icon);
2727 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2728 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2730 case TNY_HEADER_FLAG_LOW_PRIORITY:
2731 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2732 MODEST_HEADER_ICON_LOW,
2733 HILDON_ICON_SIZE_XSMALL);
2734 gtk_widget_show (priv->priority_icon);
2735 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2736 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2739 gtk_widget_hide (priv->priority_icon);
2740 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2741 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2744 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2745 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2750 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2753 ModestMsgEditWindowPrivate *priv;
2754 ModestWindowPrivate *parent_priv;
2755 gint current_format;
2757 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2759 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2760 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2762 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2763 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2765 if (current_format != file_format) {
2766 switch (file_format) {
2767 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2768 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2769 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2771 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2775 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2776 response = gtk_dialog_run (GTK_DIALOG (dialog));
2777 gtk_widget_destroy (dialog);
2778 if (response == GTK_RESPONSE_OK) {
2779 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2781 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2782 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2787 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2788 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2789 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2794 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2797 ModestMsgEditWindowPrivate *priv;
2798 WPTextBufferFormat oldfmt, fmt;
2799 gint old_position = 0;
2803 GdkColor *color = NULL;
2804 gboolean bold, bold_set, italic, italic_set;
2805 gboolean underline, underline_set;
2806 gboolean strikethrough, strikethrough_set;
2807 gboolean position_set;
2808 gboolean font_size_set, font_set, color_set;
2811 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2812 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2814 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2815 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2816 GTK_WINDOW(dialog), GTK_WINDOW (window));
2818 /* First we get the currently selected font information */
2819 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2821 switch (oldfmt.text_position) {
2822 case TEXT_POSITION_NORMAL:
2825 case TEXT_POSITION_SUPERSCRIPT:
2833 g_object_set (G_OBJECT (dialog),
2834 "bold", oldfmt.bold != FALSE,
2835 "bold-set", !oldfmt.cs.bold,
2836 "underline", oldfmt.underline != FALSE,
2837 "underline-set", !oldfmt.cs.underline,
2838 "italic", oldfmt.italic != FALSE,
2839 "italic-set", !oldfmt.cs.italic,
2840 "strikethrough", oldfmt.strikethrough != FALSE,
2841 "strikethrough-set", !oldfmt.cs.strikethrough,
2842 "color", &oldfmt.color,
2843 "color-set", !oldfmt.cs.color,
2844 "size", wp_font_size[oldfmt.font_size],
2845 "size-set", !oldfmt.cs.font_size,
2846 "position", old_position,
2847 "position-set", !oldfmt.cs.text_position,
2848 "family", wp_get_font_name (oldfmt.font),
2849 "family-set", !oldfmt.cs.font,
2852 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2853 GTK_WINDOW (dialog), GTK_WINDOW (window));
2854 gtk_widget_show_all (dialog);
2855 priv->font_dialog = dialog;
2856 response = gtk_dialog_run (GTK_DIALOG (dialog));
2857 priv->font_dialog = NULL;
2858 if (response == GTK_RESPONSE_OK) {
2860 g_object_get( dialog,
2862 "bold-set", &bold_set,
2863 "underline", &underline,
2864 "underline-set", &underline_set,
2866 "italic-set", &italic_set,
2867 "strikethrough", &strikethrough,
2868 "strikethrough-set", &strikethrough_set,
2870 "color-set", &color_set,
2872 "size-set", &font_size_set,
2873 "family", &font_name,
2874 "family-set", &font_set,
2875 "position", &position,
2876 "position-set", &position_set,
2881 if (response == GTK_RESPONSE_OK) {
2882 memset(&fmt, 0, sizeof(fmt));
2888 fmt.italic = italic;
2889 fmt.cs.italic = TRUE;
2891 if (underline_set) {
2892 fmt.underline = underline;
2893 fmt.cs.underline = TRUE;
2895 if (strikethrough_set) {
2896 fmt.strikethrough = strikethrough;
2897 fmt.cs.strikethrough = TRUE;
2902 ? TEXT_POSITION_NORMAL
2903 : ( ( position == 1 )
2904 ? TEXT_POSITION_SUPERSCRIPT
2905 : TEXT_POSITION_SUBSCRIPT );
2906 fmt.cs.text_position = TRUE;
2907 fmt.font_size = oldfmt.font_size;
2911 fmt.cs.color = TRUE;
2914 fmt.font = wp_get_font_index(font_name,
2919 if (font_size_set) {
2920 fmt.cs.font_size = TRUE;
2921 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2923 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2924 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2926 gtk_widget_destroy (dialog);
2928 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2932 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2934 ModestMsgEditWindowPrivate *priv;
2936 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2937 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2939 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2941 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2942 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2946 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2948 ModestMsgEditWindowPrivate *priv;
2950 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2951 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2953 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2955 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2956 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2961 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2963 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2965 priv->can_undo = can_undo;
2969 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2971 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2973 priv->can_redo = can_redo;
2977 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2979 ModestMsgEditWindowPrivate *priv;
2980 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2981 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2983 return priv->can_undo;
2987 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2989 ModestMsgEditWindowPrivate *priv;
2990 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2991 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2993 return priv->can_redo;
2998 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3001 GtkTextIter match_start, match_end;
3003 if (image_id == NULL)
3006 gtk_text_buffer_get_start_iter (buffer, &iter);
3008 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3009 GSList *tags = gtk_text_iter_get_tags (&match_start);
3011 for (node = tags; node != NULL; node = g_slist_next (node)) {
3012 GtkTextTag *tag = (GtkTextTag *) node->data;
3013 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3014 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3015 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3017 offset = gtk_text_iter_get_offset (&match_start);
3018 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3019 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3023 gtk_text_iter_forward_char (&iter);
3028 message_is_empty (ModestMsgEditWindow *window)
3030 ModestMsgEditWindowPrivate *priv = NULL;
3032 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3033 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3035 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3036 * so we can ignore markup.
3038 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3041 count = gtk_text_buffer_get_char_count (buf);
3047 msg_body_focus (GtkWidget *focus,
3048 GdkEventFocus *event,
3052 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3053 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3054 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3059 recpt_field_changed (GtkTextBuffer *buffer,
3060 ModestMsgEditWindow *editor)
3062 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3063 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3067 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3069 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3070 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3074 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3077 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3078 GtkTextBuffer *buffer;
3080 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3081 gtk_text_buffer_set_modified (buffer, modified);
3082 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3083 gtk_text_buffer_set_modified (buffer, modified);
3084 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3085 gtk_text_buffer_set_modified (buffer, modified);
3086 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3090 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3092 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3093 const char *account_name;
3094 GtkTextBuffer *buffer;
3096 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3097 if (gtk_text_buffer_get_modified (buffer))
3099 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3100 if (gtk_text_buffer_get_modified (buffer))
3102 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3103 if (gtk_text_buffer_get_modified (buffer))
3105 if (gtk_text_buffer_get_modified (priv->text_buffer))
3107 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3108 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3119 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3121 ModestMsgEditWindowPrivate *priv = NULL;
3123 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3124 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3126 /* check if there's no recipient added */
3127 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3128 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3129 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3130 /* no recipient contents, then select contacts */
3131 modest_msg_edit_window_open_addressbook (window, NULL);
3135 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3136 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3139 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3140 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3143 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3144 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3148 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3149 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3150 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3157 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3158 ModestMsgEditWindow *window)
3160 modest_msg_edit_window_offer_attach_file (window);
3164 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3166 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3168 return priv->clipboard_text;
3172 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3174 ModestMsgEditWindow *window)
3176 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3177 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3179 if (!GTK_WIDGET_VISIBLE (window))
3182 g_object_ref (window);
3183 text = gtk_clipboard_wait_for_text (selection_clipboard);
3185 if (priv->clipboard_text != NULL) {
3186 g_free (priv->clipboard_text);
3188 priv->clipboard_text = text;
3190 if (GTK_WIDGET_VISIBLE (window)) {
3191 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3193 g_object_unref (window);
3196 static gboolean clipboard_owner_change_idle (gpointer userdata)
3198 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3199 ModestMsgEditWindowPrivate *priv;
3201 gdk_threads_enter ();
3202 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3203 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3205 priv->clipboard_owner_idle = 0;
3206 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3207 gdk_threads_leave ();
3213 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3215 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3216 if (priv->clipboard_owner_idle == 0) {
3217 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3222 subject_field_move_cursor (GtkEntry *entry,
3223 GtkMovementStep step,
3228 if (!GTK_WIDGET_VISIBLE (window))
3231 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3235 update_window_title (ModestMsgEditWindow *window)
3237 ModestMsgEditWindowPrivate *priv = NULL;
3238 const gchar *subject;
3240 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3241 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3242 if (subject == NULL || subject[0] == '\0')
3243 subject = _("mail_va_new_email");
3245 gtk_window_set_title (GTK_WINDOW (window), subject);
3250 subject_field_changed (GtkEditable *editable,
3251 ModestMsgEditWindow *window)
3253 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3254 update_window_title (window);
3255 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3256 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3257 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3261 subject_field_insert_text (GtkEditable *editable,
3263 gint new_text_length,
3265 ModestMsgEditWindow *window)
3267 GString *result = g_string_new ("");
3269 gint result_len = 0;
3270 const gchar *entry_text = NULL;
3273 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3274 old_length = g_utf8_strlen (entry_text, -1);
3276 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3277 gunichar c = g_utf8_get_char_validated (current, 8);
3278 /* Invalid unichar, stop */
3284 result = g_string_append_unichar (result, c);
3288 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3289 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3292 /* Prevent endless recursion */
3293 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3294 g_signal_emit_by_name (editable, "insert-text",
3295 (gpointer) result->str, (gpointer) result->len,
3296 (gpointer) position, (gpointer) window);
3297 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3301 if (result_len + old_length > 1000) {
3302 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3303 dgettext("hildon-common-strings",
3304 "ckdg_ib_maximum_characters_reached"));
3307 g_string_free (result, TRUE);
3311 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3314 ModestMsgEditWindowPrivate *priv = NULL;
3316 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3317 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3319 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3322 gtk_widget_show_all (priv->find_toolbar);
3323 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3325 gtk_widget_hide_all (priv->find_toolbar);
3326 gtk_widget_grab_focus (priv->msg_body);
3332 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3334 GtkTextIter *match_start,
3335 GtkTextIter *match_end)
3337 GtkTextIter end_iter;
3338 gchar *str_casefold;
3341 gchar *range_casefold;
3344 gboolean result = FALSE;
3351 gtk_text_iter_forward_to_end (&end_iter);
3353 str_casefold = g_utf8_casefold (str, -1);
3354 str_chars_n = strlen (str);
3356 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3357 range_casefold = g_utf8_casefold (range_text, -1);
3358 range_chars_n = strlen (range_casefold);
3360 if (range_chars_n < str_chars_n) {
3361 g_free (str_casefold);
3362 g_free (range_text);
3363 g_free (range_casefold);
3367 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3368 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3369 if (!g_utf8_collate (range_subtext, str_casefold)) {
3370 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3372 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3373 match_start, match_end, NULL);
3374 g_free (found_text);
3376 g_free (range_subtext);
3380 g_free (str_casefold);
3381 g_free (range_text);
3382 g_free (range_casefold);
3389 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3390 ModestMsgEditWindow *window)
3392 gchar *current_search = NULL;
3393 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3395 GtkTextIter selection_start, selection_end;
3396 GtkTextIter match_start, match_end;
3397 gboolean continue_search = FALSE;
3399 if (message_is_empty (window)) {
3400 g_free (priv->last_search);
3401 priv->last_search = NULL;
3402 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3406 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3407 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3408 g_free (current_search);
3409 g_free (priv->last_search);
3410 priv->last_search = NULL;
3411 /* Information banner about empty search */
3412 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3416 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3417 continue_search = TRUE;
3419 g_free (priv->last_search);
3420 priv->last_search = g_strdup (current_search);
3423 if (continue_search) {
3424 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3425 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3426 &match_start, &match_end);
3428 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3430 GtkTextIter buffer_start;
3431 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3432 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3433 &match_start, &match_end);
3435 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3438 /* Mark as selected the string found in search */
3440 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3441 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3442 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3444 g_free (priv->last_search);
3445 priv->last_search = NULL;
3447 g_free (current_search);
3451 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3452 ModestMsgEditWindow *window)
3454 ModestMsgEditWindowPrivate *priv;
3456 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3458 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->find_toolbar_button), FALSE);
3462 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3464 ModestMsgEditWindowPrivate *priv;
3466 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3471 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3474 ModestMsgEditWindowPrivate *priv;
3476 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3482 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3485 ModestMsgEditWindowPrivate *priv;
3486 TnyHeader *header = NULL;
3488 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3489 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3491 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3492 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3494 if (priv->draft_msg != NULL) {
3495 g_object_unref (priv->draft_msg);
3498 if (draft != NULL) {
3499 g_object_ref (draft);
3500 header = tny_msg_get_header (draft);
3501 if (priv->msg_uid) {
3502 g_free (priv->msg_uid);
3503 priv->msg_uid = NULL;
3505 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3506 if (GTK_WIDGET_REALIZED (window)) {
3507 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3508 gtk_widget_destroy (GTK_WIDGET (window));
3514 priv->draft_msg = draft;
3518 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3519 GtkTextIter *start, GtkTextIter *end,
3522 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3523 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3526 if (tag == NULL) return;
3527 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3528 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3529 replace_with_images (window, priv->images);
3534 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3537 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3539 g_return_if_fail (TNY_IS_MIME_PART (part));
3540 tny_list_prepend (priv->attachments, (GObject *) part);
3541 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3542 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3543 gtk_widget_show_all (priv->attachments_caption);
3544 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3548 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3550 ModestMsgEditWindowPrivate *priv;
3552 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3553 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3555 return priv->msg_uid;
3559 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3560 ModestMsgEditWindowWidgetType widget_type)
3562 ModestMsgEditWindowPrivate *priv;
3564 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3565 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3567 switch (widget_type) {
3568 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3569 return priv->msg_body;
3571 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3572 return priv->to_field;
3574 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3575 return priv->cc_field;
3577 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3578 return priv->bcc_field;
3580 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3581 return priv->subject_field;
3583 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3584 return priv->attachments_view;
3592 remove_tags (WPTextBuffer *buffer)
3594 GtkTextIter start, end;
3596 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3597 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3599 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3603 on_account_removed (TnyAccountStore *account_store,
3604 TnyAccount *account,
3607 /* Do nothing if it's a store account, because we use the
3608 transport to send the messages */
3609 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3610 const gchar *parent_acc = NULL;
3611 const gchar *our_acc = NULL;
3613 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3614 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3615 /* Close this window if I'm showing a message of the removed account */
3616 if (strcmp (parent_acc, our_acc) == 0)
3617 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3622 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3624 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3626 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3632 set_zoom_do_nothing (ModestWindow *window,
3638 get_zoom_do_nothing (ModestWindow *window)
3643 typedef struct _MessageSettingsHelper {
3644 ModestMsgEditWindow *window;
3645 GSList *priority_group;
3646 GtkWidget *align_picker;
3647 } MessageSettingsHelper;
3650 on_priority_toggle (HildonCheckButton *button,
3651 MessageSettingsHelper *helper)
3654 ModestMsgEditWindowPrivate *priv;
3656 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3657 if (hildon_check_button_get_active (button)) {
3659 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3660 HildonCheckButton *node_button = (HildonCheckButton *) node->data;
3661 if ((node_button != button) &&
3662 hildon_check_button_get_active (node_button)) {
3663 hildon_check_button_set_active (node_button, FALSE);
3665 if (priv->priority_flags != (TnyHeaderFlags) g_object_get_data (G_OBJECT (button), "priority"))
3666 modest_msg_edit_window_set_priority_flags (helper->window,
3668 g_object_get_data (G_OBJECT (button),
3674 gboolean found = FALSE;
3675 /* If no one is active, activate it again */
3676 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3677 HildonCheckButton *node_button = (HildonCheckButton *) node->data;
3678 if (hildon_check_button_get_active (node_button)) {
3684 hildon_check_button_set_active (button, TRUE);
3690 on_format_picker_value_changed (HildonPickerButton *button,
3691 MessageSettingsHelper *helper)
3693 ModestMsgEditFormat new_format, old_format;
3696 switch (hildon_picker_button_get_active (button)) {
3698 new_format = MODEST_MSG_EDIT_FORMAT_HTML;
3699 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
3703 new_format = MODEST_MSG_EDIT_FORMAT_TEXT;
3704 file_format = MODEST_FILE_FORMAT_PLAIN_TEXT;
3708 old_format = modest_msg_edit_window_get_format (helper->window);
3709 if (new_format != old_format) {
3710 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (helper->window), file_format);
3712 switch (modest_msg_edit_window_get_format (helper->window)) {
3713 case MODEST_MSG_EDIT_FORMAT_TEXT:
3714 hildon_picker_button_set_active (button, 0);
3715 gtk_widget_set_sensitive (helper->align_picker, FALSE);
3717 case MODEST_MSG_EDIT_FORMAT_HTML:
3719 hildon_picker_button_set_active (button, 1);
3720 gtk_widget_set_sensitive (helper->align_picker, TRUE);
3727 on_align_picker_value_changed (HildonPickerButton *button,
3728 MessageSettingsHelper *helper)
3730 GtkJustification new_justify;
3731 ModestMsgEditFormatState *format_state = NULL;
3733 switch (hildon_picker_button_get_active (button)) {
3735 new_justify = GTK_JUSTIFY_CENTER;
3738 new_justify = GTK_JUSTIFY_RIGHT;
3742 new_justify = GTK_JUSTIFY_LEFT;
3746 format_state = modest_msg_edit_window_get_format_state (helper->window);
3747 if (format_state->justification != new_justify)
3748 format_state->justification = new_justify;
3749 modest_msg_edit_window_set_format_state (helper->window, format_state);
3750 g_free (format_state);
3754 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3758 GtkWidget *priority_hbox;
3759 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3760 GtkWidget *captioned;
3761 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3762 GtkWidget *format_picker;
3763 GtkWidget *format_selector;
3764 GtkWidget *align_selector;
3765 ModestMsgEditWindowPrivate *priv;
3766 MessageSettingsHelper helper = {0,};
3767 ModestMsgEditFormatState *format_state = NULL;
3769 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3770 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3771 helper.window = window;
3772 helper.priority_group = NULL;
3774 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3775 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3777 dialog = gtk_dialog_new ();
3778 vbox = gtk_vbox_new (FALSE, 0);
3779 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3780 gtk_widget_show (vbox);
3782 /* Priority toggles */
3783 priority_hbox = gtk_hbox_new (TRUE, 0);
3784 high_toggle = hildon_check_button_new (HILDON_SIZE_FINGER_HEIGHT);
3785 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3786 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3787 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3788 medium_toggle = hildon_check_button_new (HILDON_SIZE_FINGER_HEIGHT);
3789 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3790 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3791 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3792 low_toggle = hildon_check_button_new (HILDON_SIZE_FINGER_HEIGHT);
3793 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3794 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3795 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3796 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, FALSE, FALSE, 0);
3797 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, FALSE, FALSE, 0);
3798 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, FALSE, FALSE, 0);
3799 gtk_widget_show_all (priority_hbox);
3800 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3801 _("mcen_me_editor_message_priority"), priority_hbox);
3802 gtk_widget_show (captioned);
3803 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3805 /* format selector */
3806 format_selector = hildon_touch_selector_new_text ();
3807 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (format_selector), _("mcen_me_editor_plain_text"));
3808 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (format_selector), _("mcen_me_editor_formatted_text"));
3809 format_picker = hildon_picker_button_new (MODEST_EDITABLE_SIZE,
3810 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
3811 hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (format_picker), HILDON_TOUCH_SELECTOR (format_selector));
3812 modest_maemo_utils_set_hbutton_layout (title_sizegroup, value_sizegroup,
3813 _("mcen_me_editor_format"), format_picker);
3814 gtk_widget_show_all (format_picker);
3815 gtk_box_pack_start (GTK_BOX (vbox), format_picker, FALSE, FALSE, 0);
3817 /* alignment selector */
3818 align_selector = hildon_touch_selector_new_text ();
3819 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (align_selector), _("mcen_me_editor_align_left"));
3820 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (align_selector), _("mcen_me_editor_align_centred"));
3821 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (align_selector), _("mcen_me_editor_align_right"));
3822 helper.align_picker = hildon_picker_button_new (MODEST_EDITABLE_SIZE,
3823 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
3824 hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (helper.align_picker), HILDON_TOUCH_SELECTOR (align_selector));
3825 modest_maemo_utils_set_hbutton_layout (title_sizegroup, value_sizegroup,
3826 _("mcen_me_editor_align"), helper.align_picker);
3827 gtk_widget_show_all (helper.align_picker);
3828 gtk_box_pack_start (GTK_BOX (vbox), helper.align_picker, FALSE, FALSE, 0);
3830 g_object_unref (title_sizegroup);
3831 g_object_unref (value_sizegroup);
3832 gtk_window_set_title (GTK_WINDOW (dialog), _("TODO: Message settings"));
3834 /* Set current values */
3835 switch (priv->priority_flags) {
3836 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3837 hildon_check_button_set_active (HILDON_CHECK_BUTTON (high_toggle), TRUE);
3839 case TNY_HEADER_FLAG_LOW_PRIORITY:
3840 hildon_check_button_set_active (HILDON_CHECK_BUTTON (low_toggle), TRUE);
3843 hildon_check_button_set_active (HILDON_CHECK_BUTTON (medium_toggle), TRUE);
3847 switch (modest_msg_edit_window_get_format (window)) {
3848 case MODEST_MSG_EDIT_FORMAT_TEXT:
3849 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (format_picker), 0);
3850 gtk_widget_set_sensitive (helper.align_picker, FALSE);
3852 case MODEST_MSG_EDIT_FORMAT_HTML:
3854 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (format_picker), 1);
3855 gtk_widget_set_sensitive (helper.align_picker, TRUE);
3859 format_state = modest_msg_edit_window_get_format_state (window);
3860 switch (format_state->justification) {
3861 case GTK_JUSTIFY_RIGHT:
3862 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 2);
3864 case GTK_JUSTIFY_CENTER:
3865 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 1);
3868 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 0);
3872 g_free (format_state);
3874 /* Signal connects */
3875 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3876 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3877 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3878 g_signal_connect (G_OBJECT (format_picker), "value-changed", G_CALLBACK (on_format_picker_value_changed), &helper);
3879 g_signal_connect (G_OBJECT (helper.align_picker), "value-changed",
3880 G_CALLBACK (on_align_picker_value_changed), &helper);
3882 gtk_dialog_run (GTK_DIALOG (dialog));
3884 /* Read new values */
3886 gtk_widget_destroy (dialog);
3887 g_slist_free (helper.priority_group);
3891 static void on_message_settings (GtkAction *action,
3892 ModestMsgEditWindow *window)
3894 modest_msg_edit_window_show_msg_settings_dialog (window);
3898 static void add_button_to_menu (ModestMsgEditWindow *self,
3899 HildonAppMenu *menu,
3901 ModestDimmingRulesGroup *group,
3902 GCallback dimming_callback)
3904 if (dimming_callback)
3905 modest_dimming_rules_group_add_widget_rule (group,
3906 GTK_WIDGET (button),
3908 MODEST_WINDOW (self));
3909 hildon_app_menu_append (menu, GTK_BUTTON (button));
3912 static void add_to_menu (ModestMsgEditWindow *self,
3913 HildonAppMenu *menu,
3916 ModestDimmingRulesGroup *group,
3917 GCallback dimming_callback)
3921 button = gtk_button_new_with_label (label);
3922 g_signal_connect_after (G_OBJECT (button), "clicked",
3923 callback, (gpointer) self);
3924 add_button_to_menu (self, menu, GTK_BUTTON (button), group, dimming_callback);
3928 on_cc_button_toggled (HildonCheckButton *button,
3929 ModestMsgEditWindow *window)
3931 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3933 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3934 hildon_check_button_get_active (button));
3938 on_bcc_button_toggled (HildonCheckButton *button,
3939 ModestMsgEditWindow *window)
3941 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3943 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3944 hildon_check_button_get_active (button));
3948 on_find_toolbar_button_toggled (HildonCheckButton *button,
3949 ModestMsgEditWindow *window)
3951 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3952 modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window),
3953 hildon_check_button_get_active (button));
3958 setup_menu (ModestMsgEditWindow *self, ModestDimmingRulesGroup *group)
3960 ModestMsgEditWindowPrivate *priv = NULL;
3962 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3964 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3966 priv->app_menu = hildon_app_menu_new ();
3968 /* Settings menu buttons */
3969 add_to_menu (self, HILDON_APP_MENU (priv->app_menu), _("mcen_me_editor_checknames"),
3970 G_CALLBACK (modest_ui_actions_on_check_names),
3972 add_to_menu (self, HILDON_APP_MENU (priv->app_menu), _("mcen_me_inbox_undo"),
3973 G_CALLBACK (modest_ui_actions_on_undo),
3974 group, G_CALLBACK (modest_ui_dimming_rules_on_undo));
3976 priv->cc_button = hildon_check_button_new (0);
3977 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3978 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3980 add_button_to_menu (self, HILDON_APP_MENU (priv->app_menu), GTK_BUTTON (priv->cc_button),
3982 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3983 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3984 priv->bcc_button = hildon_check_button_new (0);
3985 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3986 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3988 add_button_to_menu (self, HILDON_APP_MENU (priv->app_menu), GTK_BUTTON (priv->bcc_button),
3990 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3991 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3993 add_to_menu (self, HILDON_APP_MENU (priv->app_menu), _("mcen_me_editor_attach_inlineimage"),
3994 G_CALLBACK (modest_ui_actions_on_insert_image),
3995 group, G_CALLBACK (modest_ui_dimming_rules_on_set_style));
3996 add_to_menu (self, HILDON_APP_MENU (priv->app_menu), _("mcen_me_inbox_remove_attachments"),
3997 G_CALLBACK (modest_ui_actions_on_remove_attachments),
3998 group, G_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3999 add_to_menu (self, HILDON_APP_MENU (priv->app_menu), _("TODO: Message settings..."),
4000 G_CALLBACK (on_message_settings),
4002 priv->find_toolbar_button = hildon_check_button_new (0);
4003 gtk_button_set_label (GTK_BUTTON (priv->find_toolbar_button), _("mcen_me_viewer_find"));
4004 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->find_toolbar_button),
4006 add_button_to_menu (self, HILDON_APP_MENU (priv->app_menu), GTK_BUTTON (priv->find_toolbar_button),
4008 g_signal_connect (G_OBJECT (priv->find_toolbar_button), "toggled",
4009 G_CALLBACK (on_find_toolbar_button_toggled), (gpointer) self);
4011 hildon_stackable_window_set_main_menu (HILDON_STACKABLE_WINDOW (self),
4012 HILDON_APP_MENU (priv->app_menu));
4016 modest_msg_edit_window_toggle_menu (HildonWindow *window,
4020 ModestMsgEditWindowPrivate *priv = NULL;
4022 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4024 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4026 gtk_widget_queue_resize (priv->app_menu);
4028 return HILDON_WINDOW_CLASS (parent_class)->toggle_menu (window, button, time);