1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
42 #include <modest-account-mgr.h>
43 #include <modest-account-mgr-helpers.h>
45 #include <widgets/modest-msg-edit-window.h>
46 #include <modest-selector-picker.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <modest-wp-text-view.h>
65 #include <wptextbuffer.h>
66 #include <hildon/hildon-pannable-area.h>
67 #include <hildon/hildon-touch-selector.h>
68 #include <hildon/hildon-picker-dialog.h>
69 #include "modest-msg-edit-window-ui-dimming.h"
71 #include "modest-hildon-includes.h"
72 #ifdef MODEST_HAVE_HILDON0_WIDGETS
73 #include <hildon-widgets/hildon-color-chooser.h>
75 #include "widgets/modest-msg-edit-window-ui.h"
76 #ifdef MODEST_HAVE_HILDON0_WIDGETS
77 #include <libgnomevfs/gnome-vfs-mime-utils.h>
79 #include <libgnomevfs/gnome-vfs-mime.h>
81 #include <modest-utils.h>
82 #include "modest-maemo-utils.h"
83 #include <modest-ui-constants.h>
86 #define DEFAULT_FONT_SIZE 3
87 #define DEFAULT_FONT 2
88 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
89 #define DEFAULT_MAIN_VBOX_SPACING 6
90 #define SUBJECT_MAX_LENGTH 1000
91 #define IMAGE_MAX_WIDTH 560
92 #define DEFAULT_FONT_SCALE 1.5
93 #define ATTACHMENT_BUTTON_WIDTH 118
95 static gboolean is_wp_text_buffer_started = FALSE;
97 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
98 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
99 static void modest_msg_edit_window_finalize (GObject *obj);
101 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
102 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
103 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
105 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
106 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
107 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
108 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
109 GtkTextIter *start, GtkTextIter *end,
111 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
112 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
113 static void subject_field_insert_text (GtkEditable *editable,
115 gint new_text_length,
117 ModestMsgEditWindow *window);
118 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
120 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
122 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
123 ModestRecptEditor *editor);
124 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
125 ModestMsgEditWindow *window);
127 /* ModestWindow methods implementation */
128 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
129 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
130 gboolean show_toolbar);
131 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
133 ModestMsgEditWindow *window);
134 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
135 static void subject_field_move_cursor (GtkEntry *entry,
136 GtkMovementStep step,
140 static void update_window_title (ModestMsgEditWindow *window);
143 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
144 ModestMsgEditWindow *window);
145 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
146 ModestMsgEditWindow *window);
147 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
149 GtkTextIter *match_start,
150 GtkTextIter *match_end);
152 static void remove_tags (WPTextBuffer *buffer);
154 static void on_account_removed (TnyAccountStore *account_store,
158 static void init_window (ModestMsgEditWindow *obj);
160 gboolean scroll_drag_timeout (gpointer userdata);
161 static void correct_scroll (ModestMsgEditWindow *w);
162 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
163 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
164 ModestMsgEditWindow *userdata);
165 static void text_buffer_mark_set (GtkTextBuffer *buffer,
168 ModestMsgEditWindow *userdata);
169 static void on_message_settings (GtkAction *action,
170 ModestMsgEditWindow *window);
171 static void setup_menu (ModestMsgEditWindow *self);
173 static void from_field_changed (HildonPickerButton *button,
174 ModestMsgEditWindow *self);
175 static void font_size_clicked (GtkToolButton *button,
176 ModestMsgEditWindow *window);
177 static void font_face_clicked (GtkToolButton *button,
178 ModestMsgEditWindow *window);
179 static void DEBUG_BUFFER (WPTextBuffer *buffer)
183 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
185 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
186 while (!gtk_text_iter_is_end (&iter)) {
187 GString *output = g_string_new ("");
188 GSList *toggled_tags;
191 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
192 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
193 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
194 GtkTextTag *tag = (GtkTextTag *) node->data;
196 g_object_get (G_OBJECT (tag), "name", &name, NULL);
197 output = g_string_append (output, name);
198 g_string_append (output, " ");
200 output = g_string_append (output, "] OPENED [ ");
201 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
202 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
203 GtkTextTag *tag = (GtkTextTag *) node->data;
205 g_object_get (G_OBJECT (tag), "name", &name, NULL);
206 output = g_string_append (output, name);
207 g_string_append (output, " ");
209 output = g_string_append (output, "]\n");
210 g_message ("%s", output->str);
211 g_string_free (output, TRUE);
212 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
214 g_message ("END BUFFER");
218 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
219 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
223 /* static gboolean */
224 /* on_key_pressed (GtkWidget *self, */
225 /* GdkEventKey *event, */
226 /* gpointer user_data); */
228 /* list my signals */
235 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
236 struct _ModestMsgEditWindowPrivate {
238 GtkWidget *header_box;
240 ModestPairList *from_field_protos;
241 GtkWidget *from_field;
242 gchar *last_from_account;
243 gchar *original_account_name;
247 GtkWidget *bcc_field;
248 GtkWidget *subject_field;
249 GtkWidget *attachments_view;
250 GtkWidget *priority_icon;
251 GtkWidget *subject_box;
252 GtkWidget *add_attachment_button;
254 GtkWidget *cc_caption;
255 GtkWidget *bcc_caption;
256 gboolean update_caption_visibility;
257 GtkWidget *attachments_caption;
259 GtkTextBuffer *text_buffer;
261 GtkWidget *font_size_toolitem;
262 GtkWidget *font_face_toolitem;
263 GtkWidget *font_color_button;
264 GtkWidget *font_color_toolitem;
265 GSList *font_items_group;
266 GtkTreeModel *faces_model;
267 gint current_face_index;
268 GtkWidget *font_tool_button_label;
269 GtkTreeModel *sizes_model;
270 gint current_size_index;
271 GtkWidget *size_tool_button_label;
273 GtkWidget *find_toolbar;
276 GtkWidget *font_dialog;
279 guint correct_scroll_idle;
280 guint scroll_drag_timeout_id;
284 TnyList *attachments;
289 TnyHeaderFlags priority_flags;
291 gboolean can_undo, can_redo;
292 gulong clipboard_change_handler_id;
293 gulong default_clipboard_change_handler_id;
294 gulong account_removed_handler_id;
295 guint clipboard_owner_idle;
296 gchar *clipboard_text;
305 GtkWidget *cc_button;
306 GtkWidget *bcc_button;
309 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
310 MODEST_TYPE_MSG_EDIT_WINDOW, \
311 ModestMsgEditWindowPrivate))
313 static GtkWindowClass *parent_class = NULL;
315 /* uncomment the following if you have defined any signals */
316 /* static guint signals[LAST_SIGNAL] = {0}; */
319 modest_msg_edit_window_get_type (void)
321 static GType my_type = 0;
323 static const GTypeInfo my_info = {
324 sizeof(ModestMsgEditWindowClass),
325 NULL, /* base init */
326 NULL, /* base finalize */
327 (GClassInitFunc) modest_msg_edit_window_class_init,
328 NULL, /* class finalize */
329 NULL, /* class data */
330 sizeof(ModestMsgEditWindow),
332 (GInstanceInitFunc) modest_msg_edit_window_init,
335 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
336 "ModestMsgEditWindow",
344 save_state (ModestWindow *self)
346 modest_widget_memory_save (modest_runtime_get_conf(),
347 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
352 restore_settings (ModestMsgEditWindow *self)
354 ModestConf *conf = NULL;
356 conf = modest_runtime_get_conf ();
358 /* Dim at start clipboard actions */
359 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
364 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
366 GObjectClass *gobject_class;
367 ModestWindowClass *modest_window_class;
368 gobject_class = (GObjectClass*) klass;
369 modest_window_class = (ModestWindowClass*) klass;
371 parent_class = g_type_class_peek_parent (klass);
372 gobject_class->finalize = modest_msg_edit_window_finalize;
374 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
375 modest_window_class->save_state_func = save_state;
376 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
378 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
382 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
384 ModestMsgEditWindowPrivate *priv;
385 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
387 priv->msg_body = NULL;
388 priv->from_field = NULL;
389 priv->to_field = NULL;
390 priv->cc_field = NULL;
391 priv->bcc_field = NULL;
392 priv->subject_field = NULL;
393 priv->attachments = TNY_LIST (tny_simple_list_new ());
394 priv->images = TNY_LIST (tny_simple_list_new ());
395 priv->images_size = 0;
396 priv->images_count = 0;
399 priv->cc_caption = NULL;
400 priv->bcc_caption = NULL;
401 priv->update_caption_visibility = FALSE;
403 priv->priority_flags = 0;
405 priv->find_toolbar = NULL;
406 priv->last_search = NULL;
408 priv->draft_msg = NULL;
409 priv->outbox_msg = NULL;
410 priv->msg_uid = NULL;
412 priv->can_undo = FALSE;
413 priv->can_redo = FALSE;
414 priv->clipboard_change_handler_id = 0;
415 priv->default_clipboard_change_handler_id = 0;
416 priv->account_removed_handler_id = 0;
417 priv->clipboard_owner_idle = 0;
418 priv->clipboard_text = NULL;
421 priv->scroll_drag_timeout_id = 0;
422 priv->correct_scroll_idle = 0;
423 priv->last_upper = 0.0;
425 priv->font_dialog = NULL;
426 priv->app_menu = NULL;
428 if (!is_wp_text_buffer_started) {
429 is_wp_text_buffer_started = TRUE;
430 wp_text_buffer_library_init ();
435 hildon_program_add_window (hildon_program_get_instance(),
441 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
443 static ModestPairList*
444 get_transports (void)
446 GSList *transports = NULL;
448 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
449 GSList *accounts = modest_account_mgr_account_names (account_mgr,
450 TRUE /* only enabled accounts. */);
452 GSList *cursor = accounts;
454 gchar *account_name = cursor->data;
455 gchar *from_string = NULL;
457 from_string = modest_account_mgr_get_from_string (account_mgr,
461 if (from_string && account_name) {
462 gchar *name = account_name;
463 ModestPair *pair = modest_pair_new ((gpointer) name,
464 (gpointer) from_string , TRUE);
465 transports = g_slist_prepend (transports, pair);
468 cursor = cursor->next;
470 g_slist_free (accounts); /* only free the accounts, not the elements,
471 * because they are used in the pairlist */
475 static void window_focus (GtkWindow *window,
479 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
483 scroll_drag_timeout (gpointer userdata)
485 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
486 ModestMsgEditWindowPrivate *priv;
488 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
490 correct_scroll_without_drag_check (win, TRUE);
492 priv->scroll_drag_timeout_id = 0;
498 correct_scroll_without_drag_check_idle (gpointer userdata)
500 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
501 ModestMsgEditWindowPrivate *priv;
503 GdkRectangle rectangle;
504 gint offset_min, offset_max;
508 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
510 insert = gtk_text_buffer_get_insert (priv->text_buffer);
511 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
513 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
514 offset_min = priv->msg_body->allocation.y + rectangle.y;
515 offset_max = offset_min + rectangle.height;
517 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
518 offset_min = MAX (offset_min - 48, 0);
519 offset_max = MIN (offset_max + 48, vadj->upper);
521 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
523 priv->correct_scroll_idle = 0;
528 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
530 ModestMsgEditWindowPrivate *priv;
532 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
534 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
537 if (priv->correct_scroll_idle > 0) {
541 priv->correct_scroll_idle = g_idle_add ((GSourceFunc) correct_scroll_without_drag_check_idle,
546 correct_scroll (ModestMsgEditWindow *w)
548 ModestMsgEditWindowPrivate *priv;
550 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
551 if (gtk_grab_get_current () == priv->msg_body) {
552 if (priv->scroll_drag_timeout_id == 0) {
553 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
559 correct_scroll_without_drag_check (w, TRUE);
563 text_buffer_end_user_action (GtkTextBuffer *buffer,
564 ModestMsgEditWindow *userdata)
567 correct_scroll (userdata);
571 text_buffer_mark_set (GtkTextBuffer *buffer,
574 ModestMsgEditWindow *userdata)
576 gtk_text_buffer_begin_user_action (buffer);
577 gtk_text_buffer_end_user_action (buffer);
581 cut_clipboard_check (GtkTextView *text_view,
584 GtkTextBuffer *buffer;
586 buffer = gtk_text_view_get_buffer (text_view);
587 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
588 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
593 copy_clipboard_check (GtkTextView *text_view,
596 GtkTextBuffer *buffer;
598 buffer = gtk_text_view_get_buffer (text_view);
599 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
600 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
605 attachment_deleted (ModestAttachmentsView *attachments_view,
608 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
613 connect_signals (ModestMsgEditWindow *obj)
615 ModestMsgEditWindowPrivate *priv;
617 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
619 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
620 G_CALLBACK (text_buffer_refresh_attributes), obj);
621 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
622 G_CALLBACK (text_buffer_can_undo), obj);
623 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
624 G_CALLBACK (text_buffer_can_redo), obj);
625 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
626 G_CALLBACK (body_changed), obj);
627 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
628 G_CALLBACK (body_changed), obj);
629 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
630 G_CALLBACK (text_buffer_end_user_action), obj);
631 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
632 G_CALLBACK (text_buffer_mark_set), obj);
633 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
634 G_CALLBACK (text_buffer_apply_tag), obj);
635 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
636 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
637 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
638 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
639 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
640 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
642 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
643 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
644 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
645 G_CALLBACK (from_field_changed), obj);
647 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
648 G_CALLBACK (msg_body_focus), obj);
649 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
650 G_CALLBACK (msg_body_focus), obj);
651 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
652 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
653 "changed", G_CALLBACK (recpt_field_changed), obj);
654 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
655 "changed", G_CALLBACK (recpt_field_changed), obj);
656 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
657 "changed", G_CALLBACK (recpt_field_changed), obj);
658 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
659 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
660 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
662 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
663 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
665 priv->clipboard_change_handler_id =
666 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
667 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
668 priv->default_clipboard_change_handler_id =
669 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
670 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
672 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
673 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
674 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
678 init_wp_text_view_style ()
680 static gboolean initialized = FALSE;
683 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
689 init_window (ModestMsgEditWindow *obj)
691 GtkWidget *to_caption, *subject_caption;
692 GtkWidget *main_vbox;
693 GtkWidget *add_attachment_align;
694 ModestMsgEditWindowPrivate *priv;
695 GtkActionGroup *action_group;
696 ModestWindowPrivate *parent_priv;
697 GdkPixbuf *window_icon = NULL;
698 GError *error = NULL;
700 GtkSizeGroup *title_size_group;
701 GtkSizeGroup *value_size_group;
702 GtkWidget *attachment_icon;
703 GtkWidget *window_box;
704 GtkWidget *window_align;
705 #if (GTK_MINOR_VERSION >= 10)
706 GdkAtom deserialize_type;
709 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
710 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
712 parent_priv->ui_manager = gtk_ui_manager_new();
713 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
714 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
716 /* Add common actions */
717 gtk_action_group_add_actions (action_group,
718 modest_msg_edit_action_entries,
719 G_N_ELEMENTS (modest_msg_edit_action_entries),
721 gtk_action_group_add_actions (action_group,
722 hildon2_msg_edit_action_entries,
723 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
725 gtk_action_group_add_toggle_actions (action_group,
726 modest_msg_edit_toggle_action_entries,
727 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
729 gtk_action_group_add_radio_actions (action_group,
730 modest_msg_edit_alignment_radio_action_entries,
731 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
733 G_CALLBACK (modest_ui_actions_on_change_justify),
735 gtk_action_group_add_radio_actions (action_group,
736 modest_msg_edit_priority_action_entries,
737 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
739 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
741 gtk_action_group_add_radio_actions (action_group,
742 modest_msg_edit_file_format_action_entries,
743 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
744 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
745 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
747 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
748 g_object_unref (action_group);
750 /* Load the UI definition */
751 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
754 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
755 g_clear_error (&error);
758 /* Add accelerators */
759 gtk_window_add_accel_group (GTK_WINDOW (obj),
760 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
762 parent_priv->menubar = NULL;
764 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
765 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
767 /* Note: This ModestPairList* must exist for as long as the picker
768 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
769 * so it can't know how to manage its memory. */
770 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
771 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
773 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
774 _("mail_va_from"), priv->from_field);
776 priv->to_field = modest_recpt_editor_new ();
777 priv->cc_field = modest_recpt_editor_new ();
778 priv->bcc_field = modest_recpt_editor_new ();
779 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
780 priv->priority_icon = gtk_image_new ();
781 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
782 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
783 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
784 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
785 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
786 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
787 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
788 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
789 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
790 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
791 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
792 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
793 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
794 add_attachment_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
795 gtk_alignment_set_padding (GTK_ALIGNMENT (add_attachment_align), 0, 0, MODEST_MARGIN_DEFAULT, 0);
796 gtk_container_add (GTK_CONTAINER (add_attachment_align), priv->add_attachment_button);
797 gtk_box_pack_start (GTK_BOX (priv->subject_box), add_attachment_align, FALSE, FALSE, 0);
798 priv->attachments_view = modest_attachments_view_new (NULL);
799 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
800 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
802 priv->header_box = gtk_vbox_new (FALSE, 0);
804 to_caption = modest_maemo_utils_create_captioned_with_size_type
805 (title_size_group, value_size_group,
806 _("mail_va_to"), FALSE, priv->to_field,
807 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
808 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
809 (title_size_group, value_size_group,
810 _("mail_va_cc"), FALSE, priv->cc_field,
811 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
812 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
813 (title_size_group, value_size_group,
814 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
815 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
816 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
817 _("mail_va_subject"), FALSE, priv->subject_box);
818 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
819 _("mail_va_attachment"),
821 priv->attachments_view,
822 HILDON_SIZE_AUTO_WIDTH |
823 HILDON_SIZE_AUTO_HEIGHT);
824 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
825 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
826 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
827 g_object_unref (title_size_group);
828 g_object_unref (value_size_group);
830 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
831 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
832 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
833 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
834 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
835 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
836 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
838 init_wp_text_view_style ();
840 priv->msg_body = modest_wp_text_view_new ();
843 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
844 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
845 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
846 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
847 #if (GTK_MINOR_VERSION >= 10)
848 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
849 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
851 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
852 deserialize_type, TRUE);
854 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
856 priv->find_toolbar = hildon_find_toolbar_new (NULL);
857 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
859 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
861 priv->pannable = hildon_pannable_area_new ();
863 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
864 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
865 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
867 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
868 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
869 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
871 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
872 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox),
873 hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable)));
874 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
876 window_box = gtk_vbox_new (FALSE, 0);
877 gtk_container_add (GTK_CONTAINER(obj), window_box);
879 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
881 /* Set window icon */
882 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
884 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
885 g_object_unref (window_icon);
890 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
892 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
894 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
895 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
896 priv->clipboard_change_handler_id))
897 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
898 priv->clipboard_change_handler_id);
899 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
900 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
901 priv->default_clipboard_change_handler_id))
902 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
903 priv->default_clipboard_change_handler_id);
905 if (priv->account_removed_handler_id &&
906 g_signal_handler_is_connected (modest_runtime_get_account_store (),
907 priv->account_removed_handler_id))
908 g_signal_handler_disconnect(modest_runtime_get_account_store (),
909 priv->account_removed_handler_id);
913 modest_msg_edit_window_finalize (GObject *obj)
915 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
917 /* Sanity check: shouldn't be needed, the window mgr should
918 call this function before */
919 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
921 if (priv->font_dialog != NULL) {
922 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
925 if (priv->clipboard_text != NULL) {
926 g_free (priv->clipboard_text);
927 priv->clipboard_text = NULL;
930 if (priv->draft_msg != NULL) {
931 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
932 if (TNY_IS_HEADER (header)) {
933 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
934 modest_window_mgr_unregister_header (mgr, header);
936 g_object_unref (priv->draft_msg);
937 priv->draft_msg = NULL;
939 if (priv->outbox_msg != NULL) {
940 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
941 if (TNY_IS_HEADER (header)) {
942 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
943 modest_window_mgr_unregister_header (mgr, header);
945 g_object_unref (priv->outbox_msg);
946 priv->outbox_msg = NULL;
948 if (priv->correct_scroll_idle > 0) {
949 g_source_remove (priv->correct_scroll_idle);
950 priv->correct_scroll_idle = 0;
952 if (priv->scroll_drag_timeout_id > 0) {
953 g_source_remove (priv->scroll_drag_timeout_id);
954 priv->scroll_drag_timeout_id = 0;
956 if (priv->clipboard_owner_idle > 0) {
957 g_source_remove (priv->clipboard_owner_idle);
958 priv->clipboard_owner_idle = 0;
960 if (priv->original_account_name)
961 g_free (priv->original_account_name);
962 g_free (priv->msg_uid);
963 g_free (priv->last_search);
964 g_object_unref (priv->faces_model);
965 g_object_unref (priv->sizes_model);
966 g_object_unref (priv->attachments);
967 g_object_unref (priv->images);
969 /* This had to stay alive for as long as the picker that used it: */
970 modest_pair_list_free (priv->from_field_protos);
972 G_OBJECT_CLASS(parent_class)->finalize (obj);
976 pixbuf_from_stream (TnyStream *stream,
977 const gchar *mime_type,
978 guint64 *stream_size,
979 ModestMsgEditWindow *self)
981 GdkPixbufLoader *loader;
984 GError *error = NULL;
988 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
990 if (loader == NULL) {
996 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
998 tny_stream_reset (TNY_STREAM (stream));
999 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1000 unsigned char read_buffer[128];
1002 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1004 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1007 /* Allow some UI responsiveness */
1008 while (gtk_events_pending ())
1009 gtk_main_iteration ();
1011 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1013 gdk_pixbuf_loader_close (loader, &error);
1016 g_error_free (error);
1017 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1019 g_object_ref (pixbuf);
1020 g_object_unref (loader);
1025 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1026 GdkPixbuf *new_pixbuf;
1028 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1029 gdk_pixbuf_get_width (pixbuf);
1030 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1031 g_object_unref (pixbuf);
1032 pixbuf = new_pixbuf;
1036 *stream_size = size;
1042 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1044 ModestMsgEditWindowPrivate *priv;
1047 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1049 for (iter = tny_list_create_iterator (attachments);
1050 !tny_iterator_is_done (iter);
1051 tny_iterator_next (iter)) {
1052 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1053 const gchar *cid = tny_mime_part_get_content_id (part);
1054 const gchar *mime_type = tny_mime_part_get_content_type (part);
1055 if ((cid != NULL)&&(mime_type != NULL)) {
1056 guint64 stream_size;
1057 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1058 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1061 g_object_unref (stream);
1063 if (pixbuf != NULL) {
1064 priv->images_count ++;
1065 priv->images_size += stream_size;
1066 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1067 g_object_unref (pixbuf);
1070 g_object_unref (part);
1072 g_object_unref (iter);
1076 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1078 TnyMimePart *parent = NULL;
1079 const gchar *content_type = NULL;
1080 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1082 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1084 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1085 parent = g_object_ref (msg);
1086 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1087 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1090 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1091 iter = tny_list_create_iterator (parts);
1092 while (!tny_iterator_is_done (iter)) {
1094 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1095 content_type = tny_mime_part_get_content_type (part);
1096 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1100 g_object_unref (part);
1102 tny_iterator_next (iter);
1104 g_object_unref (iter);
1105 g_object_unref (parts);
1108 if (parent != NULL) {
1109 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1112 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1113 iter = tny_list_create_iterator (parts);
1114 while (!tny_iterator_is_done (iter)) {
1116 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1117 content_type = tny_mime_part_get_content_type (part);
1118 if (content_type && g_str_has_prefix (content_type, "image/")) {
1119 tny_list_prepend (priv->images, (GObject *) part);
1121 g_object_unref (part);
1122 tny_iterator_next (iter);
1124 g_object_unref (iter);
1125 g_object_unref (parts);
1126 g_object_unref (parent);
1131 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1134 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1136 for (iter = tny_list_create_iterator (attachments) ;
1137 !tny_iterator_is_done (iter);
1138 tny_iterator_next (iter)) {
1139 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1140 const gchar *cid = tny_mime_part_get_content_id (part);
1142 char *invalid = NULL;
1143 gint int_cid = strtol (cid, &invalid, 10);
1144 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1145 priv->next_cid = int_cid + 1;
1148 g_object_unref (part);
1150 g_object_unref (iter);
1154 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1157 gchar *to, *cc, *bcc, *subject;
1159 ModestMsgEditWindowPrivate *priv;
1160 ModestWindowPrivate *parent_priv;
1162 TnyHeaderFlags priority_flags;
1163 TnyFolder *msg_folder;
1164 gboolean is_html = FALSE;
1165 gboolean field_view_set;
1167 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1168 g_return_if_fail (TNY_IS_MSG (msg));
1170 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1171 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1173 header = tny_msg_get_header (msg);
1174 to = tny_header_dup_to (header);
1175 cc = tny_header_dup_cc (header);
1176 bcc = tny_header_dup_bcc (header);
1177 subject = tny_header_dup_subject (header);
1178 priority_flags = tny_header_get_priority (header);
1181 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1183 field_view_set = TRUE;
1185 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1186 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1187 gtk_widget_show (priv->cc_caption);
1188 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1189 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1190 gtk_widget_hide (priv->cc_caption);
1191 field_view_set = FALSE;
1193 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1195 field_view_set = TRUE;
1197 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1198 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1199 gtk_widget_show (priv->bcc_caption);
1200 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1201 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1202 gtk_widget_hide (priv->bcc_caption);
1203 field_view_set = FALSE;
1205 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1209 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1210 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1213 update_window_title (self);
1215 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1216 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1218 if ((body == NULL)||(body[0] == '\0')) {
1220 body = modest_text_utils_convert_to_html ("");
1223 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1224 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1227 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1230 /* Add attachments to the view */
1231 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1232 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1233 if (tny_list_get_length (priv->attachments) == 0) {
1234 gtk_widget_hide (priv->attachments_caption);
1236 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1237 gtk_widget_show_all (priv->attachments_caption);
1239 get_related_images (self, msg);
1240 update_next_cid (self, priv->attachments);
1241 update_next_cid (self, priv->images);
1242 replace_with_images (self, priv->images);
1244 if (preserve_is_rich && !is_html) {
1245 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1246 /* Get the default format required from configuration */
1247 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1248 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1251 /* Set the default focus depending on having already a To: field or not */
1252 if ((!to)||(*to == '\0')) {
1253 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1255 gtk_widget_grab_focus (priv->msg_body);
1258 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1260 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1261 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1263 modest_msg_edit_window_set_modified (self, FALSE);
1265 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1266 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1267 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1268 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1270 if (priv->msg_uid) {
1271 g_free (priv->msg_uid);
1272 priv->msg_uid = NULL;
1275 /* we should set a reference to the incoming message if it is a draft */
1276 msg_folder = tny_msg_get_folder (msg);
1278 if (modest_tny_folder_is_local_folder (msg_folder)) {
1279 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1280 if (type == TNY_FOLDER_TYPE_INVALID)
1281 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1283 if (type == TNY_FOLDER_TYPE_DRAFTS)
1284 priv->draft_msg = g_object_ref(msg);
1285 if (type == TNY_FOLDER_TYPE_OUTBOX)
1286 priv->outbox_msg = g_object_ref(msg);
1287 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1289 g_object_unref (msg_folder);
1300 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1302 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1303 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1304 GtkWidget *placeholder;
1305 GtkWidget *tool_item;
1310 GtkWidget *sizes_menu;
1311 GtkWidget *fonts_menu;
1315 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1316 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1317 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1318 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1320 /* Font color placeholder */
1321 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1322 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1325 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1326 priv->font_color_button = hildon_color_button_new ();
1327 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1328 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1329 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1330 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1331 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1332 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1333 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1334 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1336 G_CALLBACK (modest_msg_edit_window_color_button_change),
1339 /* Font size and face placeholder */
1340 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1341 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1343 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1344 priv->size_tool_button_label = gtk_label_new (NULL);
1345 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1346 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1347 size_text, "</span>", NULL);
1348 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1350 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1351 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1352 sizes_menu = gtk_menu_new ();
1353 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1354 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1357 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1358 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1360 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1364 if (wp_font_size[size_index] == 12)
1365 priv->current_size_index = size_index;
1369 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1370 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1371 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1372 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1373 priv->font_size_toolitem = tool_item;
1376 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1377 priv->font_tool_button_label = gtk_label_new (NULL);
1378 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1379 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1381 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1382 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1383 fonts_menu = gtk_menu_new ();
1384 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1385 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1388 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1390 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1391 0, wp_get_font_name (font_index),
1394 if (font_index == DEFAULT_FONT)
1395 priv->current_face_index = font_index;
1397 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1398 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1399 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1400 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1401 priv->font_face_toolitem = tool_item;
1403 /* Set expand and homogeneous for remaining items */
1404 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1405 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1406 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1407 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1408 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1409 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1410 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1411 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1412 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1414 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1415 will not show the tool items added to the placeholders) */
1416 gtk_widget_show_all (parent_priv->toolbar);
1418 /* Set the no show all *after* showing all items. We do not
1419 want the toolbar to be shown with a show all because it
1420 could go agains the gconf setting regarding showing or not
1421 the toolbar of the editor window */
1422 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1428 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1431 ModestWindowPrivate *parent_priv;
1432 ModestMsgEditWindowPrivate *priv;
1433 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1434 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1435 ModestWindowMgr *mgr = NULL;
1437 g_return_val_if_fail (msg, NULL);
1438 g_return_val_if_fail (account_name, NULL);
1440 mgr = modest_runtime_get_window_mgr ();
1442 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1444 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1445 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1447 /* Menubar. Update the state of some toggles */
1448 priv->from_field_protos = get_transports ();
1449 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1450 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1451 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1452 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1454 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1455 hildon_touch_selector_get_current_text
1456 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1457 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1458 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1461 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1463 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1465 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1467 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1469 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1470 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1471 /* Add common dimming rules */
1472 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1473 modest_msg_edit_window_toolbar_dimming_entries,
1474 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1475 MODEST_WINDOW (obj));
1476 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1477 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1478 MODEST_WINDOW (obj));
1479 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1480 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1481 MODEST_WINDOW (obj));
1482 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1483 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1484 MODEST_WINDOW (obj));
1485 /* Insert dimming rules group for this window */
1486 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1487 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1489 /* Setup app menu */
1490 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1492 /* Checks the dimming rules */
1493 g_object_unref (toolbar_rules_group);
1494 g_object_unref (clipboard_rules_group);
1495 gtk_widget_hide (priv->priority_icon);
1496 gtk_widget_queue_resize (priv->subject_box);
1497 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1499 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1501 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1502 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1503 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1504 priv->update_caption_visibility = TRUE;
1506 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1508 /* Track account-removed signal, this window should be closed
1509 in the case we're creating a mail associated to the account
1511 priv->account_removed_handler_id =
1512 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1514 G_CALLBACK(on_account_removed),
1517 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1519 return (ModestWindow*) obj;
1523 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1525 GString **string_buffer = (GString **) user_data;
1527 *string_buffer = g_string_append (*string_buffer, buffer);
1533 * @result: A new string which should be freed with g_free().
1536 get_formatted_data (ModestMsgEditWindow *edit_window)
1538 ModestMsgEditWindowPrivate *priv;
1539 GString *string_buffer = g_string_new ("");
1541 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1543 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1545 modest_text_utils_hyperlinkify (string_buffer);
1547 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1549 return g_string_free (string_buffer, FALSE);
1554 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1557 const gchar *account_name;
1558 ModestMsgEditWindowPrivate *priv;
1559 TnyIterator *att_iter;
1561 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1563 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1565 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1566 g_return_val_if_fail (account_name, NULL);
1569 /* don't free these (except from) */
1570 data = g_slice_new0 (MsgData);
1571 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1573 data->account_name = g_strdup (account_name);
1574 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1575 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1576 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1577 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1578 if (priv->draft_msg) {
1579 data->draft_msg = g_object_ref (priv->draft_msg);
1580 } else if (priv->outbox_msg) {
1581 data->draft_msg = g_object_ref (priv->outbox_msg);
1583 data->draft_msg = NULL;
1586 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1588 gtk_text_buffer_get_bounds (buf, &b, &e);
1589 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1591 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1592 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1594 data->html_body = NULL;
1596 /* deep-copy the data */
1597 att_iter = tny_list_create_iterator (priv->attachments);
1598 data->attachments = NULL;
1599 while (!tny_iterator_is_done (att_iter)) {
1600 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1601 if (!(TNY_IS_MIME_PART(part))) {
1602 g_warning ("strange data in attachment list");
1603 g_object_unref (part);
1604 tny_iterator_next (att_iter);
1607 data->attachments = g_list_append (data->attachments,
1609 tny_iterator_next (att_iter);
1611 g_object_unref (att_iter);
1613 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1614 att_iter = tny_list_create_iterator (priv->images);
1615 data->images = NULL;
1616 while (!tny_iterator_is_done (att_iter)) {
1617 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1619 if (!(TNY_IS_MIME_PART(part))) {
1620 g_warning ("strange data in attachment list");
1621 g_object_unref (part);
1622 tny_iterator_next (att_iter);
1625 cid = tny_mime_part_get_content_id (part);
1627 gchar *image_tag_id;
1628 GtkTextTag *image_tag;
1630 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1631 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1632 g_free (image_tag_id);
1634 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1636 ((gtk_text_iter_has_tag (&iter, image_tag))||
1637 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1638 data->images = g_list_append (data->images,
1639 g_object_ref (part));
1641 g_object_unref (part);
1642 tny_iterator_next (att_iter);
1644 g_object_unref (att_iter);
1646 data->priority_flags = priv->priority_flags;
1653 unref_gobject (GObject *obj, gpointer data)
1655 if (!G_IS_OBJECT(obj))
1657 g_object_unref (obj);
1661 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1664 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1672 g_free (data->from);
1673 g_free (data->subject);
1674 g_free (data->plain_body);
1675 g_free (data->html_body);
1676 g_free (data->account_name);
1678 if (data->draft_msg != NULL) {
1679 g_object_unref (data->draft_msg);
1680 data->draft_msg = NULL;
1683 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1684 g_list_free (data->attachments);
1685 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1686 g_list_free (data->images);
1688 g_slice_free (MsgData, data);
1692 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1694 guint64 *parts_size)
1696 ModestMsgEditWindowPrivate *priv;
1698 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1700 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1702 /* TODO: add images */
1703 *parts_size += priv->images_size;
1704 *parts_count += priv->images_count;
1709 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1712 ModestMsgEditWindowPrivate *priv = NULL;
1713 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1715 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1717 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1719 return MODEST_MSG_EDIT_FORMAT_HTML;
1721 return MODEST_MSG_EDIT_FORMAT_TEXT;
1725 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1726 ModestMsgEditFormat format)
1728 ModestMsgEditWindowPrivate *priv;
1730 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1731 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1734 case MODEST_MSG_EDIT_FORMAT_HTML:
1735 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1737 case MODEST_MSG_EDIT_FORMAT_TEXT:
1738 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1741 g_return_if_reached ();
1745 ModestMsgEditFormatState *
1746 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1748 ModestMsgEditFormatState *format_state = NULL;
1749 ModestMsgEditWindowPrivate *priv;
1750 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1752 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1753 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1755 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1757 format_state = g_new0 (ModestMsgEditFormatState, 1);
1758 format_state->bold = buffer_format->bold&0x1;
1759 format_state->italics = buffer_format->italic&0x1;
1760 format_state->bullet = buffer_format->bullet&0x1;
1761 format_state->color = buffer_format->color;
1762 format_state->font_size = buffer_format->font_size;
1763 format_state->font_family = wp_get_font_name (buffer_format->font);
1764 format_state->justification = buffer_format->justification;
1765 g_free (buffer_format);
1767 return format_state;
1772 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1773 const ModestMsgEditFormatState *format_state)
1775 ModestMsgEditWindowPrivate *priv;
1776 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1777 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1778 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1779 g_return_if_fail (format_state != NULL);
1781 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1782 gtk_widget_grab_focus (priv->msg_body);
1783 buffer_format->bold = (format_state->bold != FALSE);
1784 buffer_format->italic = (format_state->italics != FALSE);
1785 buffer_format->color = format_state->color;
1786 buffer_format->font_size = format_state->font_size;
1787 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1788 buffer_format->justification = format_state->justification;
1789 buffer_format->bullet = format_state->bullet;
1791 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1793 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1794 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1795 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1796 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1797 buffer_format->cs.font = (buffer_format->font != current_format->font);
1798 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1799 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1801 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1802 if (buffer_format->cs.bold) {
1803 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1804 GINT_TO_POINTER (buffer_format->bold&0x1));
1806 if (buffer_format->cs.italic) {
1807 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1808 GINT_TO_POINTER (buffer_format->italic&0x1));
1810 if (buffer_format->cs.color) {
1811 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1812 GINT_TO_POINTER (&(buffer_format->color)));
1814 if (buffer_format->cs.font_size) {
1815 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1816 GINT_TO_POINTER (buffer_format->font_size));
1818 if (buffer_format->cs.justification) {
1819 switch (buffer_format->justification) {
1820 case GTK_JUSTIFY_LEFT:
1821 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1822 GINT_TO_POINTER(TRUE));
1824 case GTK_JUSTIFY_CENTER:
1825 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1826 GINT_TO_POINTER(TRUE));
1828 case GTK_JUSTIFY_RIGHT:
1829 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1830 GINT_TO_POINTER(TRUE));
1837 if (buffer_format->cs.font) {
1838 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1839 GINT_TO_POINTER (buffer_format->font));
1841 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1842 if (buffer_format->cs.bullet) {
1843 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1844 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1846 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1848 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1850 g_free (buffer_format);
1851 g_free (current_format);
1853 /* Check dimming rules */
1854 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1855 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1859 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1861 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1863 ModestWindowPrivate *parent_priv;
1864 ModestMsgEditWindowPrivate *priv;
1866 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1867 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1869 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1870 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1871 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1872 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1874 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1875 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1876 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1879 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1881 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1882 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1884 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1885 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1887 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1888 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1891 switch (buffer_format->justification)
1893 case GTK_JUSTIFY_LEFT:
1894 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1896 case GTK_JUSTIFY_CENTER:
1897 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1899 case GTK_JUSTIFY_RIGHT:
1900 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1907 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1909 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1910 G_CALLBACK (modest_msg_edit_window_color_button_change),
1912 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1913 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1914 G_CALLBACK (modest_msg_edit_window_color_button_change),
1917 if (priv->current_size_index != buffer_format->font_size) {
1921 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
1922 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
1926 priv->current_size_index = buffer_format->font_size;
1928 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
1929 markup = g_strconcat ("<span font_family='Sans'>",
1930 size_text, "</span>", NULL);
1932 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1936 gtk_tree_path_free (path);
1939 if (priv->current_face_index != buffer_format->font) {
1943 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
1944 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
1948 priv->current_face_index = buffer_format->font;
1949 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
1950 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
1951 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1958 g_free (buffer_format);
1962 #ifdef MODEST_HILDON_VERSION_0
1964 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1967 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1968 ModestMsgEditWindowPrivate *priv;
1969 GtkWidget *dialog = NULL;
1971 GdkColor *new_color = NULL;
1973 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1974 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1976 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1977 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1978 g_free (buffer_format);
1980 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
1981 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1982 if (new_color != NULL) {
1983 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1984 (gpointer) new_color);
1987 gtk_widget_destroy (dialog);
1992 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1995 ModestMsgEditWindowPrivate *priv;
1996 GtkWidget *dialog = NULL;
1998 GdkColor *old_color = NULL;
1999 const GdkColor *new_color = NULL;
2001 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2002 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2004 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2005 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2007 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2008 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2009 if (new_color != NULL)
2010 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2012 gtk_widget_destroy (dialog);
2018 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2021 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2022 ModestMsgEditWindowPrivate *priv;
2023 GtkWidget *dialog = NULL;
2025 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2026 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2028 dialog = hildon_color_chooser_new ();
2029 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2030 g_free (buffer_format);
2032 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2034 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2035 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2038 gtk_widget_destroy (dialog);
2043 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2046 ModestMsgEditWindowPrivate *priv;
2047 GtkWidget *dialog = NULL;
2048 GdkColor *old_color = NULL;
2050 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2051 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2053 dialog = hildon_color_chooser_new ();
2054 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2056 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2058 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2059 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2061 gtk_widget_destroy (dialog);
2064 #endif /*!MODEST_HILDON_VERSION_0*/
2069 create_stream_for_uri (const gchar* uri)
2074 TnyStream *result = NULL;
2076 GnomeVFSHandle *handle = NULL;
2077 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2078 if (test == GNOME_VFS_OK) {
2079 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2080 /* Streams over OBEX (Bluetooth) are not seekable but
2081 * we expect them to be (we might need to read them
2082 * several times). So if this is a Bluetooth URI just
2083 * read the whole file into memory (this is not a fast
2084 * protocol so we can assume that these files are not
2085 * going to be very big) */
2086 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2087 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2088 TnyStream *memstream = tny_camel_mem_stream_new ();
2089 tny_stream_write_to_stream (vfssstream, memstream);
2090 g_object_unref (vfssstream);
2093 result = vfssstream;
2101 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2104 ModestMsgEditWindowPrivate *priv;
2105 GtkWidget *dialog = NULL;
2107 GSList *uris = NULL;
2108 GSList *uri_node = NULL;
2110 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2112 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2113 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2114 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2116 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2118 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2119 GTK_WINDOW (dialog), GTK_WINDOW (window));
2121 response = gtk_dialog_run (GTK_DIALOG (dialog));
2123 case GTK_RESPONSE_OK:
2124 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2129 gtk_widget_destroy (dialog);
2131 /* The operation could take some time so allow the dialog to be closed */
2132 while (gtk_events_pending ())
2133 gtk_main_iteration ();
2135 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2137 GnomeVFSHandle *handle = NULL;
2138 GnomeVFSResult result;
2139 GtkTextIter position;
2140 GtkTextMark *insert_mark;
2142 uri = (const gchar *) uri_node->data;
2143 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2144 if (result == GNOME_VFS_OK) {
2146 GnomeVFSFileInfo *info;
2147 gchar *filename, *basename, *escaped_filename;
2148 TnyMimePart *mime_part;
2150 const gchar *mime_type = NULL;
2151 GnomeVFSURI *vfs_uri;
2152 guint64 stream_size;
2154 gnome_vfs_close (handle);
2155 vfs_uri = gnome_vfs_uri_new (uri);
2157 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2158 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2159 g_free (escaped_filename);
2160 gnome_vfs_uri_unref (vfs_uri);
2161 info = gnome_vfs_file_info_new ();
2163 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2164 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2166 mime_type = gnome_vfs_file_info_get_mime_type (info);
2168 mime_part = tny_platform_factory_new_mime_part
2169 (modest_runtime_get_platform_factory ());
2171 TnyStream *stream = create_stream_for_uri (uri);
2173 if (stream == NULL) {
2175 modest_platform_information_banner (NULL, NULL,
2176 _FM("sfil_ib_opening_not_allowed"));
2178 g_object_unref (mime_part);
2179 gnome_vfs_file_info_unref (info);
2183 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2185 content_id = g_strdup_printf ("%d", priv->next_cid);
2186 tny_mime_part_set_content_id (mime_part, content_id);
2187 g_free (content_id);
2190 basename = g_path_get_basename (filename);
2191 tny_mime_part_set_filename (mime_part, basename);
2194 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2196 if (pixbuf != NULL) {
2197 priv->images_size += stream_size;
2198 priv->images_count ++;
2199 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2200 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2201 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2202 g_object_unref (pixbuf);
2204 tny_list_prepend (priv->images, (GObject *) mime_part);
2205 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2207 modest_platform_information_banner (NULL, NULL,
2208 _("mail_ib_file_operation_failed"));
2212 g_object_unref (mime_part);
2213 gnome_vfs_file_info_unref (info);
2222 on_attach_file_response (GtkDialog *dialog,
2226 GSList *uris = NULL;
2228 GnomeVFSFileSize total_size, allowed_size;
2229 ModestMsgEditWindow *window;
2230 ModestMsgEditWindowPrivate *priv;
2235 case GTK_RESPONSE_OK:
2236 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2242 window = MODEST_MSG_EDIT_WINDOW (user_data);
2243 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2245 /* allowed size is the maximum size - what's already there */
2246 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2247 &att_num, &att_size);
2248 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2251 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2253 const gchar *uri = (const gchar *) uri_node->data;
2256 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2258 if (total_size > allowed_size) {
2259 g_warning ("%s: total size: %u",
2260 __FUNCTION__, (unsigned int)total_size);
2263 allowed_size -= total_size;
2265 g_slist_foreach (uris, (GFunc) g_free, NULL);
2266 g_slist_free (uris);
2268 gtk_widget_destroy (GTK_WIDGET (dialog));
2272 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2274 GtkWidget *dialog = NULL;
2275 ModestMsgEditWindowPrivate *priv;
2277 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2279 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2281 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2284 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2285 GTK_FILE_CHOOSER_ACTION_OPEN);
2286 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2287 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2288 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2289 GTK_WINDOW (dialog), GTK_WINDOW (window));
2291 /* Connect to response & show */
2292 g_signal_connect (dialog, "response",
2293 G_CALLBACK (on_attach_file_response), window);
2294 gtk_widget_show (dialog);
2299 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2301 GnomeVFSFileSize allowed_size)
2304 GnomeVFSHandle *handle = NULL;
2305 ModestMsgEditWindowPrivate *priv;
2306 GnomeVFSResult result;
2307 GnomeVFSFileSize size = 0;
2308 g_return_val_if_fail (window, 0);
2309 g_return_val_if_fail (uri, 0);
2311 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2313 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2314 if (result == GNOME_VFS_OK) {
2315 TnyMimePart *mime_part;
2317 const gchar *mime_type = NULL;
2319 gchar *escaped_filename;
2322 GnomeVFSFileInfo *info;
2323 GnomeVFSURI *vfs_uri;
2325 gnome_vfs_close (handle);
2326 vfs_uri = gnome_vfs_uri_new (uri);
2329 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2330 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2331 g_free (escaped_filename);
2332 gnome_vfs_uri_unref (vfs_uri);
2334 info = gnome_vfs_file_info_new ();
2336 if (gnome_vfs_get_file_info (uri,
2338 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2340 mime_type = gnome_vfs_file_info_get_mime_type (info);
2341 mime_part = tny_platform_factory_new_mime_part
2342 (modest_runtime_get_platform_factory ());
2344 /* try to get the attachment's size; this may fail for weird
2345 * file systems, like obex, upnp... */
2346 if (allowed_size != 0 &&
2347 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2349 if (size > allowed_size) {
2350 modest_platform_information_banner (NULL, NULL,
2351 _FM("sfil_ib_opening_not_allowed"));
2355 g_warning ("%s: could not get attachment size", __FUNCTION__);
2357 stream = create_stream_for_uri (uri);
2359 if (stream == NULL) {
2361 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2363 g_object_unref (mime_part);
2364 gnome_vfs_file_info_unref (info);
2368 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2369 g_object_unref (stream);
2371 content_id = g_strdup_printf ("%d", priv->next_cid);
2372 tny_mime_part_set_content_id (mime_part, content_id);
2373 g_free (content_id);
2376 basename = g_path_get_basename (filename);
2377 tny_mime_part_set_filename (mime_part, basename);
2380 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2381 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2383 info->size == 0, info->size);
2384 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2385 gtk_widget_show_all (priv->attachments_caption);
2386 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2388 g_object_unref (mime_part);
2389 gnome_vfs_file_info_unref (info);
2396 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2399 ModestMsgEditWindowPrivate *priv;
2402 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2403 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2405 if (att_list == NULL) {
2406 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2407 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2408 g_object_unref (att_list);
2413 g_object_ref (att_list);
2416 if (tny_list_get_length (att_list) == 0) {
2417 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2419 gboolean dialog_response;
2420 gchar *message = NULL;
2421 gchar *filename = NULL;
2423 if (tny_list_get_length (att_list) == 1) {
2425 iter = tny_list_create_iterator (att_list);
2426 part = (TnyMimePart *) tny_iterator_get_current (iter);
2427 g_object_unref (iter);
2428 if (TNY_IS_MSG (part)) {
2429 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2431 filename = tny_header_dup_subject (header);
2432 g_object_unref (header);
2434 if (filename == NULL) {
2435 filename = g_strdup (_("mail_va_no_subject"));
2438 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2440 g_object_unref (part);
2442 filename = g_strdup ("");
2444 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2445 "emev_nc_delete_attachments",
2446 tny_list_get_length (att_list)), filename);
2449 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2453 if (dialog_response != GTK_RESPONSE_OK) {
2454 g_object_unref (att_list);
2458 for (iter = tny_list_create_iterator (att_list);
2459 !tny_iterator_is_done (iter);
2460 tny_iterator_next (iter)) {
2461 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2462 const gchar *att_id;
2463 tny_list_remove (priv->attachments, (GObject *) mime_part);
2465 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2467 if (tny_list_get_length (priv->attachments) == 0)
2468 gtk_widget_hide (priv->attachments_caption);
2469 att_id = tny_mime_part_get_content_id (mime_part);
2471 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2473 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2474 g_object_unref (mime_part);
2476 g_object_unref (iter);
2479 g_object_unref (att_list);
2481 /* if the last attachment has been removed, focus the Subject: field */
2482 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2483 gtk_widget_grab_focus (priv->subject_field);
2487 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2490 ModestMsgEditWindowPrivate *priv;
2491 GdkColor *new_color;
2492 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2494 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2495 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2498 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2500 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2502 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2504 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2509 font_size_clicked (GtkToolButton *button,
2510 ModestMsgEditWindow *window)
2512 ModestMsgEditWindowPrivate *priv;
2513 GtkWidget *selector, *dialog;
2515 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2517 selector = hildon_touch_selector_new ();
2518 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2519 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2521 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2522 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2524 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2528 WPTextBufferFormat format;
2530 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2532 memset (&format, 0, sizeof (format));
2533 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2535 format.cs.font_size = TRUE;
2536 format.cs.text_position = TRUE;
2537 format.cs.font = TRUE;
2538 format.font_size = new_index;
2539 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2541 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2542 GINT_TO_POINTER (new_index)))
2543 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2545 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2546 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2547 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2548 size_text, "</span>", NULL);
2550 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2554 gtk_widget_destroy (dialog);
2556 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2561 font_face_clicked (GtkToolButton *button,
2562 ModestMsgEditWindow *window)
2564 ModestMsgEditWindowPrivate *priv;
2565 GtkWidget *selector, *dialog;
2566 GtkCellRenderer *renderer;
2568 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2570 selector = hildon_touch_selector_new ();
2571 renderer = gtk_cell_renderer_text_new ();
2572 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2573 renderer, "family", 0, "text", 0, NULL);
2574 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2576 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2577 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2579 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2580 gint new_font_index;
2584 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2585 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2586 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2590 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2592 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2593 GINT_TO_POINTER(new_font_index)))
2594 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2596 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2597 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2599 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2603 gtk_tree_path_free (path);
2606 gtk_widget_destroy (dialog);
2608 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2613 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2616 ModestMsgEditWindowPrivate *priv = NULL;
2617 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2619 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2620 if (!priv->update_caption_visibility)
2623 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2625 gtk_widget_show (priv->cc_caption);
2627 gtk_widget_hide (priv->cc_caption);
2629 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2633 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2636 ModestMsgEditWindowPrivate *priv = NULL;
2637 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2639 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2640 if (!priv->update_caption_visibility)
2643 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2645 gtk_widget_show (priv->bcc_caption);
2647 gtk_widget_hide (priv->bcc_caption);
2649 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2653 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2654 ModestRecptEditor *editor)
2656 ModestMsgEditWindowPrivate *priv;
2658 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2659 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2661 /* we check for low-mem; in that case, show a warning, and don't allow
2662 * for the addressbook
2664 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2667 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2669 if (editor == NULL) {
2670 GtkWidget *view_focus;
2671 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2673 /* This code should be kept in sync with ModestRecptEditor. The
2674 textview inside the recpt editor is the one that really gets the
2675 focus. As it's inside a scrolled window, and this one inside the
2676 hbox recpt editor inherits from, we'll need to go up in the
2677 hierarchy to know if the text view is part of the recpt editor
2678 or if it's a different text entry */
2680 if (gtk_widget_get_parent (view_focus)) {
2681 GtkWidget *first_parent;
2683 first_parent = gtk_widget_get_parent (view_focus);
2684 if (gtk_widget_get_parent (first_parent) &&
2685 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2686 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2691 editor = MODEST_RECPT_EDITOR (priv->to_field);
2695 modest_address_book_select_addresses (editor);
2700 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2702 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2704 modest_msg_edit_window_open_addressbook (window, NULL);
2708 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2709 gboolean show_toolbar)
2711 ModestWindowPrivate *parent_priv;
2713 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2714 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2716 /* We can not just use the code of
2717 modest_msg_edit_window_setup_toolbar because it has a
2718 mixture of both initialization and creation code. */
2720 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2722 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2726 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2727 TnyHeaderFlags priority_flags)
2729 ModestMsgEditWindowPrivate *priv;
2730 ModestWindowPrivate *parent_priv;
2732 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2734 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2735 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2737 if (priv->priority_flags != priority_flags) {
2738 GtkAction *priority_action = NULL;
2740 priv->priority_flags = priority_flags;
2742 switch (priority_flags) {
2743 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2744 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2745 MODEST_HEADER_ICON_HIGH,
2746 HILDON_ICON_SIZE_SMALL);
2747 gtk_widget_show (priv->priority_icon);
2748 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2749 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2751 case TNY_HEADER_FLAG_LOW_PRIORITY:
2752 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2753 MODEST_HEADER_ICON_LOW,
2754 HILDON_ICON_SIZE_SMALL);
2755 gtk_widget_show (priv->priority_icon);
2756 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2757 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2760 gtk_widget_hide (priv->priority_icon);
2761 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2762 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2765 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2766 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2768 gtk_widget_queue_resize (priv->subject_box);
2772 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2775 ModestMsgEditWindowPrivate *priv;
2776 ModestWindowPrivate *parent_priv;
2777 gint current_format;
2779 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2781 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2782 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2784 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2785 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2787 if (current_format != file_format) {
2788 switch (file_format) {
2789 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2790 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2791 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2793 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2797 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2798 response = gtk_dialog_run (GTK_DIALOG (dialog));
2799 gtk_widget_destroy (dialog);
2800 if (response == GTK_RESPONSE_OK) {
2801 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2803 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2804 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2809 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2810 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2811 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2816 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2819 ModestMsgEditWindowPrivate *priv;
2820 WPTextBufferFormat oldfmt, fmt;
2821 gint old_position = 0;
2825 GdkColor *color = NULL;
2826 gboolean bold, bold_set, italic, italic_set;
2827 gboolean underline, underline_set;
2828 gboolean strikethrough, strikethrough_set;
2829 gboolean position_set;
2830 gboolean font_size_set, font_set, color_set;
2833 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2834 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2836 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2837 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2838 GTK_WINDOW(dialog), GTK_WINDOW (window));
2840 /* First we get the currently selected font information */
2841 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2843 switch (oldfmt.text_position) {
2844 case TEXT_POSITION_NORMAL:
2847 case TEXT_POSITION_SUPERSCRIPT:
2855 g_object_set (G_OBJECT (dialog),
2856 "bold", oldfmt.bold != FALSE,
2857 "bold-set", !oldfmt.cs.bold,
2858 "underline", oldfmt.underline != FALSE,
2859 "underline-set", !oldfmt.cs.underline,
2860 "italic", oldfmt.italic != FALSE,
2861 "italic-set", !oldfmt.cs.italic,
2862 "strikethrough", oldfmt.strikethrough != FALSE,
2863 "strikethrough-set", !oldfmt.cs.strikethrough,
2864 "color", &oldfmt.color,
2865 "color-set", !oldfmt.cs.color,
2866 "size", wp_font_size[oldfmt.font_size],
2867 "size-set", !oldfmt.cs.font_size,
2868 "position", old_position,
2869 "position-set", !oldfmt.cs.text_position,
2870 "family", wp_get_font_name (oldfmt.font),
2871 "family-set", !oldfmt.cs.font,
2874 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2875 GTK_WINDOW (dialog), GTK_WINDOW (window));
2876 gtk_widget_show_all (dialog);
2877 priv->font_dialog = dialog;
2878 response = gtk_dialog_run (GTK_DIALOG (dialog));
2879 priv->font_dialog = NULL;
2880 if (response == GTK_RESPONSE_OK) {
2882 g_object_get( dialog,
2884 "bold-set", &bold_set,
2885 "underline", &underline,
2886 "underline-set", &underline_set,
2888 "italic-set", &italic_set,
2889 "strikethrough", &strikethrough,
2890 "strikethrough-set", &strikethrough_set,
2892 "color-set", &color_set,
2894 "size-set", &font_size_set,
2895 "family", &font_name,
2896 "family-set", &font_set,
2897 "position", &position,
2898 "position-set", &position_set,
2903 if (response == GTK_RESPONSE_OK) {
2904 memset(&fmt, 0, sizeof(fmt));
2910 fmt.italic = italic;
2911 fmt.cs.italic = TRUE;
2913 if (underline_set) {
2914 fmt.underline = underline;
2915 fmt.cs.underline = TRUE;
2917 if (strikethrough_set) {
2918 fmt.strikethrough = strikethrough;
2919 fmt.cs.strikethrough = TRUE;
2924 ? TEXT_POSITION_NORMAL
2925 : ( ( position == 1 )
2926 ? TEXT_POSITION_SUPERSCRIPT
2927 : TEXT_POSITION_SUBSCRIPT );
2928 fmt.cs.text_position = TRUE;
2929 fmt.font_size = oldfmt.font_size;
2933 fmt.cs.color = TRUE;
2936 fmt.font = wp_get_font_index(font_name,
2941 if (font_size_set) {
2942 fmt.cs.font_size = TRUE;
2943 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2945 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2946 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2948 gtk_widget_destroy (dialog);
2950 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2954 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2956 ModestMsgEditWindowPrivate *priv;
2958 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2959 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2961 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2963 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2964 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2968 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2970 ModestMsgEditWindowPrivate *priv;
2972 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2973 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2975 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2977 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2978 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2983 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2985 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2987 priv->can_undo = can_undo;
2991 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2993 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2995 priv->can_redo = can_redo;
2999 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3001 ModestMsgEditWindowPrivate *priv;
3002 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3003 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3005 return priv->can_undo;
3009 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3011 ModestMsgEditWindowPrivate *priv;
3012 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3013 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3015 return priv->can_redo;
3020 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3023 GtkTextIter match_start, match_end;
3025 if (image_id == NULL)
3028 gtk_text_buffer_get_start_iter (buffer, &iter);
3030 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3031 GSList *tags = gtk_text_iter_get_tags (&match_start);
3033 for (node = tags; node != NULL; node = g_slist_next (node)) {
3034 GtkTextTag *tag = (GtkTextTag *) node->data;
3035 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3036 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3037 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3039 offset = gtk_text_iter_get_offset (&match_start);
3040 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3041 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3045 gtk_text_iter_forward_char (&iter);
3050 message_is_empty (ModestMsgEditWindow *window)
3052 ModestMsgEditWindowPrivate *priv = NULL;
3054 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3055 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3057 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3058 * so we can ignore markup.
3060 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3063 count = gtk_text_buffer_get_char_count (buf);
3069 msg_body_focus (GtkWidget *focus,
3070 GdkEventFocus *event,
3074 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3075 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3076 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3081 recpt_field_changed (GtkTextBuffer *buffer,
3082 ModestMsgEditWindow *editor)
3084 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3085 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3089 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3091 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3092 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3096 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3099 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3100 GtkTextBuffer *buffer;
3102 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3103 gtk_text_buffer_set_modified (buffer, modified);
3104 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3105 gtk_text_buffer_set_modified (buffer, modified);
3106 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3107 gtk_text_buffer_set_modified (buffer, modified);
3108 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3112 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3114 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3115 const char *account_name;
3116 GtkTextBuffer *buffer;
3118 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3119 if (gtk_text_buffer_get_modified (buffer))
3121 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3122 if (gtk_text_buffer_get_modified (buffer))
3124 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3125 if (gtk_text_buffer_get_modified (buffer))
3127 if (gtk_text_buffer_get_modified (priv->text_buffer))
3129 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3130 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3141 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3143 ModestMsgEditWindowPrivate *priv = NULL;
3145 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3146 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3148 /* check if there's no recipient added */
3149 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3150 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3151 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3152 /* no recipient contents, then select contacts */
3153 modest_msg_edit_window_open_addressbook (window, NULL);
3157 g_object_ref (window);
3158 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3159 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3160 g_object_unref (window);
3163 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3164 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3165 g_object_unref (window);
3168 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3169 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3170 g_object_unref (window);
3174 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3175 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3176 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3177 g_object_unref (window);
3184 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3185 ModestMsgEditWindow *window)
3187 modest_msg_edit_window_offer_attach_file (window);
3191 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3193 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3195 return priv->clipboard_text;
3199 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3201 ModestMsgEditWindow *window)
3203 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3204 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3206 if (!GTK_WIDGET_VISIBLE (window))
3209 g_object_ref (window);
3210 text = gtk_clipboard_wait_for_text (selection_clipboard);
3212 if (priv->clipboard_text != NULL) {
3213 g_free (priv->clipboard_text);
3215 priv->clipboard_text = text;
3217 if (GTK_WIDGET_VISIBLE (window)) {
3218 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3220 g_object_unref (window);
3223 static gboolean clipboard_owner_change_idle (gpointer userdata)
3225 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3226 ModestMsgEditWindowPrivate *priv;
3228 gdk_threads_enter ();
3229 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3230 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3232 priv->clipboard_owner_idle = 0;
3233 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3234 gdk_threads_leave ();
3240 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3242 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3243 if (priv->clipboard_owner_idle == 0) {
3244 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3249 subject_field_move_cursor (GtkEntry *entry,
3250 GtkMovementStep step,
3255 if (!GTK_WIDGET_VISIBLE (window))
3258 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3262 update_window_title (ModestMsgEditWindow *window)
3264 ModestMsgEditWindowPrivate *priv = NULL;
3265 const gchar *subject;
3267 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3268 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3269 if (subject == NULL || subject[0] == '\0')
3270 subject = _("mail_va_new_email");
3272 gtk_window_set_title (GTK_WINDOW (window), subject);
3277 subject_field_changed (GtkEditable *editable,
3278 ModestMsgEditWindow *window)
3280 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3281 update_window_title (window);
3282 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3283 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3284 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3288 subject_field_insert_text (GtkEditable *editable,
3290 gint new_text_length,
3292 ModestMsgEditWindow *window)
3294 GString *result = g_string_new ("");
3296 gint result_len = 0;
3297 const gchar *entry_text = NULL;
3300 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3301 old_length = g_utf8_strlen (entry_text, -1);
3303 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3304 gunichar c = g_utf8_get_char_validated (current, 8);
3305 /* Invalid unichar, stop */
3311 result = g_string_append_unichar (result, c);
3315 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3316 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3319 /* Prevent endless recursion */
3320 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3321 g_signal_emit_by_name (editable, "insert-text",
3322 (gpointer) result->str, (gpointer) result->len,
3323 (gpointer) position, (gpointer) window);
3324 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3328 if (result_len + old_length > 1000) {
3329 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3330 _CS("ckdg_ib_maximum_characters_reached"));
3332 g_string_free (result, TRUE);
3336 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3339 ModestMsgEditWindowPrivate *priv = NULL;
3341 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3342 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3344 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3347 gtk_widget_show_all (priv->find_toolbar);
3348 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3350 gtk_widget_hide_all (priv->find_toolbar);
3351 gtk_widget_grab_focus (priv->msg_body);
3356 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3358 GtkTextIter *match_start,
3359 GtkTextIter *match_end)
3361 GtkTextIter end_iter;
3362 gchar *str_casefold;
3365 gchar *range_casefold;
3368 gboolean result = FALSE;
3375 gtk_text_iter_forward_to_end (&end_iter);
3377 str_casefold = g_utf8_casefold (str, -1);
3378 str_chars_n = strlen (str);
3380 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3381 range_casefold = g_utf8_casefold (range_text, -1);
3382 range_chars_n = strlen (range_casefold);
3384 if (range_chars_n < str_chars_n) {
3385 g_free (str_casefold);
3386 g_free (range_text);
3387 g_free (range_casefold);
3391 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3392 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3393 if (!g_utf8_collate (range_subtext, str_casefold)) {
3394 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3396 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3397 match_start, match_end, NULL);
3398 g_free (found_text);
3400 g_free (range_subtext);
3404 g_free (str_casefold);
3405 g_free (range_text);
3406 g_free (range_casefold);
3413 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3414 ModestMsgEditWindow *window)
3416 gchar *current_search = NULL;
3417 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3419 GtkTextIter selection_start, selection_end;
3420 GtkTextIter match_start, match_end;
3421 gboolean continue_search = FALSE;
3423 if (message_is_empty (window)) {
3424 g_free (priv->last_search);
3425 priv->last_search = NULL;
3426 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3430 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3431 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3432 g_free (current_search);
3433 g_free (priv->last_search);
3434 priv->last_search = NULL;
3435 /* Information banner about empty search */
3436 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3440 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3441 continue_search = TRUE;
3443 g_free (priv->last_search);
3444 priv->last_search = g_strdup (current_search);
3447 if (continue_search) {
3448 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3449 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3450 &match_start, &match_end);
3452 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3454 GtkTextIter buffer_start;
3455 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3456 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3457 &match_start, &match_end);
3459 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3462 /* Mark as selected the string found in search */
3464 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3465 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3466 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3468 g_free (priv->last_search);
3469 priv->last_search = NULL;
3471 g_free (current_search);
3475 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3477 ModestMsgEditWindowPrivate *priv;
3479 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3484 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3487 ModestMsgEditWindowPrivate *priv;
3489 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3494 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3495 ModestMsgEditWindow *window)
3497 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3501 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3504 ModestMsgEditWindowPrivate *priv;
3505 TnyHeader *header = NULL;
3507 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3508 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3510 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3511 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3513 if (priv->draft_msg != NULL) {
3514 g_object_unref (priv->draft_msg);
3517 if (draft != NULL) {
3518 g_object_ref (draft);
3519 header = tny_msg_get_header (draft);
3520 if (priv->msg_uid) {
3521 g_free (priv->msg_uid);
3522 priv->msg_uid = NULL;
3524 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3525 if (GTK_WIDGET_REALIZED (window)) {
3526 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3527 gtk_widget_destroy (GTK_WIDGET (window));
3533 priv->draft_msg = draft;
3537 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3538 GtkTextIter *start, GtkTextIter *end,
3541 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3542 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3545 if (tag == NULL) return;
3546 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3547 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3548 replace_with_images (window, priv->images);
3553 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3556 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3558 g_return_if_fail (TNY_IS_MIME_PART (part));
3559 tny_list_prepend (priv->attachments, (GObject *) part);
3560 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3561 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3562 gtk_widget_show_all (priv->attachments_caption);
3563 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3567 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3569 ModestMsgEditWindowPrivate *priv;
3571 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3572 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3574 return priv->msg_uid;
3578 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3579 ModestMsgEditWindowWidgetType widget_type)
3581 ModestMsgEditWindowPrivate *priv;
3583 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3584 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3586 switch (widget_type) {
3587 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3588 return priv->msg_body;
3590 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3591 return priv->to_field;
3593 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3594 return priv->cc_field;
3596 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3597 return priv->bcc_field;
3599 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3600 return priv->subject_field;
3602 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3603 return priv->attachments_view;
3611 remove_tags (WPTextBuffer *buffer)
3613 GtkTextIter start, end;
3615 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3616 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3618 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3622 on_account_removed (TnyAccountStore *account_store,
3623 TnyAccount *account,
3626 /* Do nothing if it's a store account, because we use the
3627 transport to send the messages */
3628 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3629 const gchar *parent_acc = NULL;
3630 const gchar *our_acc = NULL;
3632 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3633 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3634 /* Close this window if I'm showing a message of the removed account */
3635 if (strcmp (parent_acc, our_acc) == 0)
3636 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3641 from_field_changed (HildonPickerButton *button,
3642 ModestMsgEditWindow *self)
3644 ModestMsgEditWindowPrivate *priv;
3645 gboolean has_old_signature, has_new_signature;
3647 GtkTextIter match_start, match_end;
3648 ModestAccountMgr *mgr;
3650 gchar *full_signature;
3652 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3654 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3655 mgr = modest_runtime_get_account_mgr ();
3656 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3657 if (has_old_signature) {
3658 full_signature = g_strconcat ("\n--\n", signature, NULL);
3659 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3660 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3662 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3663 &match_start, &match_end, NULL)) {
3666 g_free (full_signature);
3670 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3671 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3672 if (has_new_signature) {
3673 full_signature = g_strconcat ("\n--\n", signature, NULL);
3674 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3675 g_free (full_signature);
3680 typedef struct _MessageSettingsHelper {
3681 ModestMsgEditWindow *window;
3682 GSList *priority_group;
3683 GSList *format_group;
3684 GtkToggleButton *current_priority;
3685 GtkToggleButton *current_format;
3686 } MessageSettingsHelper;
3689 on_priority_toggle (GtkToggleButton *button,
3690 MessageSettingsHelper *helper)
3693 ModestMsgEditWindowPrivate *priv;
3695 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3696 if (gtk_toggle_button_get_active (button)) {
3698 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3699 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3700 if ((node_button != button) &&
3701 gtk_toggle_button_get_active (node_button)) {
3702 gtk_toggle_button_set_active (node_button, FALSE);
3705 helper->current_priority = button;
3707 gboolean found = FALSE;
3708 /* If no one is active, activate it again */
3709 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3710 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3711 if (gtk_toggle_button_get_active (node_button)) {
3717 gtk_toggle_button_set_active (button, TRUE);
3723 on_format_toggle (GtkToggleButton *button,
3724 MessageSettingsHelper *helper)
3727 ModestMsgEditWindowPrivate *priv;
3729 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3730 if (gtk_toggle_button_get_active (button)) {
3732 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3733 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3734 if ((node_button != button) &&
3735 gtk_toggle_button_get_active (node_button)) {
3736 gtk_toggle_button_set_active (node_button, FALSE);
3739 helper->current_format = button;
3741 gboolean found = FALSE;
3742 /* If no one is active, activate it again */
3743 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3744 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3745 if (gtk_toggle_button_get_active (node_button)) {
3751 gtk_toggle_button_set_active (button, TRUE);
3758 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3763 GtkWidget *priority_hbox;
3764 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3765 GtkWidget *captioned;
3766 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3767 GtkWidget *format_hbox;
3768 GtkWidget *html_toggle, *text_toggle;
3769 ModestMsgEditWindowPrivate *priv;
3770 MessageSettingsHelper helper = {0,};
3772 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3773 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3774 helper.window = window;
3775 helper.priority_group = NULL;
3776 helper.format_group = NULL;
3778 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3779 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3781 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3782 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3783 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3784 vbox = gtk_vbox_new (FALSE, 0);
3785 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
3786 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
3787 gtk_container_add (GTK_CONTAINER (align), vbox);
3788 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
3789 gtk_widget_show (align);
3790 gtk_widget_show (vbox);
3792 /* Priority toggles */
3793 priority_hbox = gtk_hbox_new (TRUE, 0);
3794 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3795 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3796 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3797 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3798 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3799 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3800 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3801 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3802 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3803 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3804 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3805 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3806 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3807 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3808 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3809 gtk_widget_show_all (priority_hbox);
3810 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3811 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3812 gtk_widget_show (captioned);
3813 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3815 /* format toggles */
3816 format_hbox = gtk_hbox_new (TRUE, 0);
3817 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3818 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3819 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3820 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3821 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3822 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3823 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3824 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3825 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3826 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3827 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3828 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3829 gtk_widget_show_all (format_hbox);
3830 gtk_widget_show (format_hbox);
3831 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3834 g_object_unref (title_sizegroup);
3835 g_object_unref (value_sizegroup);
3837 /* Set current values */
3838 switch (priv->priority_flags) {
3839 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3840 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3841 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3843 case TNY_HEADER_FLAG_LOW_PRIORITY:
3844 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3845 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3848 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3849 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3853 switch (modest_msg_edit_window_get_format (window)) {
3854 case MODEST_MSG_EDIT_FORMAT_TEXT:
3855 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3856 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3858 case MODEST_MSG_EDIT_FORMAT_HTML:
3860 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3861 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3865 /* Signal connects */
3866 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3867 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3868 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3869 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3870 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3872 /* Save settings if the user clicked on done */
3873 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3874 TnyHeaderFlags flags;
3875 ModestMsgEditFormat old_format, new_format;
3877 /* Set priority flags */
3878 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3879 if (priv->priority_flags != flags)
3880 modest_msg_edit_window_set_priority_flags (window, flags);
3882 /* Set edit format */
3883 old_format = modest_msg_edit_window_get_format (window);
3884 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3885 if (old_format != new_format) {
3886 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3887 modest_msg_edit_window_set_file_format (window, file_format);
3891 gtk_widget_destroy (dialog);
3892 g_slist_free (helper.priority_group);
3896 on_message_settings (GtkAction *action,
3897 ModestMsgEditWindow *window)
3899 modest_msg_edit_window_show_msg_settings_dialog (window);
3903 on_cc_button_toggled (HildonCheckButton *button,
3904 ModestMsgEditWindow *window)
3906 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3908 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3909 hildon_check_button_get_active (button));
3913 on_bcc_button_toggled (HildonCheckButton *button,
3914 ModestMsgEditWindow *window)
3916 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3918 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3919 hildon_check_button_get_active (button));
3923 setup_menu (ModestMsgEditWindow *self)
3925 ModestMsgEditWindowPrivate *priv = NULL;
3927 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3929 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3931 /* Settings menu buttons */
3932 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3933 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3935 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3936 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3937 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3939 priv->cc_button = hildon_check_button_new (0);
3940 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3941 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3943 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3945 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3946 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3947 priv->bcc_button = hildon_check_button_new (0);
3948 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3949 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3951 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3953 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3954 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3956 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3957 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3958 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3959 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3960 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3961 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3962 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3963 APP_MENU_CALLBACK (on_message_settings),
3965 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3966 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),