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 g_object_ref (self);
1050 for (iter = tny_list_create_iterator (attachments);
1051 !tny_iterator_is_done (iter);
1052 tny_iterator_next (iter)) {
1053 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1054 const gchar *cid = tny_mime_part_get_content_id (part);
1055 const gchar *mime_type = tny_mime_part_get_content_type (part);
1056 if ((cid != NULL)&&(mime_type != NULL)) {
1057 guint64 stream_size;
1058 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1059 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1062 g_object_unref (stream);
1064 if (pixbuf != NULL) {
1065 priv->images_count ++;
1066 priv->images_size += stream_size;
1067 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1068 g_object_unref (pixbuf);
1071 g_object_unref (part);
1073 g_object_unref (iter);
1074 g_object_unref (self);
1078 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1080 TnyMimePart *parent = NULL;
1081 const gchar *content_type = NULL;
1082 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1084 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1086 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1087 parent = g_object_ref (msg);
1088 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1089 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1092 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1093 iter = tny_list_create_iterator (parts);
1094 while (!tny_iterator_is_done (iter)) {
1096 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1097 content_type = tny_mime_part_get_content_type (part);
1098 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1102 g_object_unref (part);
1104 tny_iterator_next (iter);
1106 g_object_unref (iter);
1107 g_object_unref (parts);
1110 if (parent != NULL) {
1111 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1114 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1115 iter = tny_list_create_iterator (parts);
1116 while (!tny_iterator_is_done (iter)) {
1118 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1119 content_type = tny_mime_part_get_content_type (part);
1120 if (content_type && g_str_has_prefix (content_type, "image/")) {
1121 tny_list_prepend (priv->images, (GObject *) part);
1123 g_object_unref (part);
1124 tny_iterator_next (iter);
1126 g_object_unref (iter);
1127 g_object_unref (parts);
1128 g_object_unref (parent);
1133 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1136 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1138 for (iter = tny_list_create_iterator (attachments) ;
1139 !tny_iterator_is_done (iter);
1140 tny_iterator_next (iter)) {
1141 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1142 const gchar *cid = tny_mime_part_get_content_id (part);
1144 char *invalid = NULL;
1145 gint int_cid = strtol (cid, &invalid, 10);
1146 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1147 priv->next_cid = int_cid + 1;
1150 g_object_unref (part);
1152 g_object_unref (iter);
1156 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1159 gchar *to, *cc, *bcc, *subject;
1161 ModestMsgEditWindowPrivate *priv;
1162 ModestWindowPrivate *parent_priv;
1164 TnyHeaderFlags priority_flags;
1165 TnyFolder *msg_folder;
1166 gboolean is_html = FALSE;
1167 gboolean field_view_set;
1169 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1170 g_return_if_fail (TNY_IS_MSG (msg));
1172 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1173 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1175 header = tny_msg_get_header (msg);
1176 to = tny_header_dup_to (header);
1177 cc = tny_header_dup_cc (header);
1178 bcc = tny_header_dup_bcc (header);
1179 subject = tny_header_dup_subject (header);
1180 priority_flags = tny_header_get_priority (header);
1183 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1185 field_view_set = TRUE;
1187 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1188 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1189 gtk_widget_show (priv->cc_caption);
1190 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1191 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1192 gtk_widget_hide (priv->cc_caption);
1193 field_view_set = FALSE;
1195 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1197 field_view_set = TRUE;
1199 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1200 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1201 gtk_widget_show (priv->bcc_caption);
1202 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1203 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1204 gtk_widget_hide (priv->bcc_caption);
1205 field_view_set = FALSE;
1207 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1211 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1212 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1215 update_window_title (self);
1217 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1218 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1220 if ((body == NULL)||(body[0] == '\0')) {
1222 body = modest_text_utils_convert_to_html ("");
1225 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1226 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1229 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1232 /* Add attachments to the view */
1233 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1234 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1235 if (tny_list_get_length (priv->attachments) == 0) {
1236 gtk_widget_hide (priv->attachments_caption);
1238 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1239 gtk_widget_show_all (priv->attachments_caption);
1241 get_related_images (self, msg);
1242 update_next_cid (self, priv->attachments);
1243 update_next_cid (self, priv->images);
1244 replace_with_images (self, priv->images);
1246 if (preserve_is_rich && !is_html) {
1247 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1248 /* Get the default format required from configuration */
1249 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1250 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1253 /* Set the default focus depending on having already a To: field or not */
1254 if ((!to)||(*to == '\0')) {
1255 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1257 gtk_widget_grab_focus (priv->msg_body);
1260 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1262 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1263 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1265 modest_msg_edit_window_set_modified (self, FALSE);
1267 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1268 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1269 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1270 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1272 if (priv->msg_uid) {
1273 g_free (priv->msg_uid);
1274 priv->msg_uid = NULL;
1277 /* we should set a reference to the incoming message if it is a draft */
1278 msg_folder = tny_msg_get_folder (msg);
1280 if (modest_tny_folder_is_local_folder (msg_folder)) {
1281 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1282 if (type == TNY_FOLDER_TYPE_INVALID)
1283 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1285 if (type == TNY_FOLDER_TYPE_DRAFTS)
1286 priv->draft_msg = g_object_ref(msg);
1287 if (type == TNY_FOLDER_TYPE_OUTBOX)
1288 priv->outbox_msg = g_object_ref(msg);
1289 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1291 g_object_unref (msg_folder);
1302 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1304 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1305 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1306 GtkWidget *placeholder;
1307 GtkWidget *tool_item;
1312 GtkWidget *sizes_menu;
1313 GtkWidget *fonts_menu;
1317 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1318 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1319 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1320 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1322 /* Font color placeholder */
1323 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1324 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1327 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1328 priv->font_color_button = hildon_color_button_new ();
1329 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1330 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1331 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1332 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1333 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1334 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1335 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1336 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1338 G_CALLBACK (modest_msg_edit_window_color_button_change),
1341 /* Font size and face placeholder */
1342 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1343 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1345 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1346 priv->size_tool_button_label = gtk_label_new (NULL);
1347 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1348 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1349 size_text, "</span>", NULL);
1350 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1352 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1353 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1354 sizes_menu = gtk_menu_new ();
1355 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1356 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1359 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1360 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1362 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1366 if (wp_font_size[size_index] == 12)
1367 priv->current_size_index = size_index;
1371 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1372 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1373 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1374 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1375 priv->font_size_toolitem = tool_item;
1378 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1379 priv->font_tool_button_label = gtk_label_new (NULL);
1380 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1381 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1383 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1384 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1385 fonts_menu = gtk_menu_new ();
1386 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1387 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1390 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1392 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1393 0, wp_get_font_name (font_index),
1396 if (font_index == DEFAULT_FONT)
1397 priv->current_face_index = font_index;
1399 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1400 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1401 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1402 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1403 priv->font_face_toolitem = tool_item;
1405 /* Set expand and homogeneous for remaining items */
1406 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1407 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1408 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1409 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1410 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1411 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1412 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1413 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1414 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1416 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1417 will not show the tool items added to the placeholders) */
1418 gtk_widget_show_all (parent_priv->toolbar);
1420 /* Set the no show all *after* showing all items. We do not
1421 want the toolbar to be shown with a show all because it
1422 could go agains the gconf setting regarding showing or not
1423 the toolbar of the editor window */
1424 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1430 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1433 ModestWindowPrivate *parent_priv;
1434 ModestMsgEditWindowPrivate *priv;
1435 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1436 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1437 ModestWindowMgr *mgr = NULL;
1439 g_return_val_if_fail (msg, NULL);
1440 g_return_val_if_fail (account_name, NULL);
1442 mgr = modest_runtime_get_window_mgr ();
1444 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1446 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1447 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1449 /* Menubar. Update the state of some toggles */
1450 priv->from_field_protos = get_transports ();
1451 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1452 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1453 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1454 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1456 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1457 hildon_touch_selector_get_current_text
1458 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1459 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1460 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1463 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1465 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1467 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1469 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1471 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1472 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1473 /* Add common dimming rules */
1474 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1475 modest_msg_edit_window_toolbar_dimming_entries,
1476 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1477 MODEST_WINDOW (obj));
1478 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1479 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1480 MODEST_WINDOW (obj));
1481 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1482 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1483 MODEST_WINDOW (obj));
1484 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1485 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1486 MODEST_WINDOW (obj));
1487 /* Insert dimming rules group for this window */
1488 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1489 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1491 /* Setup app menu */
1492 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1494 /* Checks the dimming rules */
1495 g_object_unref (toolbar_rules_group);
1496 g_object_unref (clipboard_rules_group);
1497 gtk_widget_hide (priv->priority_icon);
1498 gtk_widget_queue_resize (priv->subject_box);
1499 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1501 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1503 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1504 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1505 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1506 priv->update_caption_visibility = TRUE;
1508 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1510 /* Track account-removed signal, this window should be closed
1511 in the case we're creating a mail associated to the account
1513 priv->account_removed_handler_id =
1514 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1516 G_CALLBACK(on_account_removed),
1519 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1521 return (ModestWindow*) obj;
1525 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1527 GString **string_buffer = (GString **) user_data;
1529 *string_buffer = g_string_append (*string_buffer, buffer);
1535 * @result: A new string which should be freed with g_free().
1538 get_formatted_data (ModestMsgEditWindow *edit_window)
1540 ModestMsgEditWindowPrivate *priv;
1541 GString *string_buffer = g_string_new ("");
1543 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1545 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1547 modest_text_utils_hyperlinkify (string_buffer);
1549 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1551 return g_string_free (string_buffer, FALSE);
1556 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1559 const gchar *account_name;
1560 ModestMsgEditWindowPrivate *priv;
1561 TnyIterator *att_iter;
1563 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1565 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1567 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1568 g_return_val_if_fail (account_name, NULL);
1571 /* don't free these (except from) */
1572 data = g_slice_new0 (MsgData);
1573 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1575 data->account_name = g_strdup (account_name);
1576 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1577 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1578 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1579 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1580 if (priv->draft_msg) {
1581 data->draft_msg = g_object_ref (priv->draft_msg);
1582 } else if (priv->outbox_msg) {
1583 data->draft_msg = g_object_ref (priv->outbox_msg);
1585 data->draft_msg = NULL;
1588 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1590 gtk_text_buffer_get_bounds (buf, &b, &e);
1591 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1593 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1594 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1596 data->html_body = NULL;
1598 /* deep-copy the data */
1599 att_iter = tny_list_create_iterator (priv->attachments);
1600 data->attachments = NULL;
1601 while (!tny_iterator_is_done (att_iter)) {
1602 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1603 if (!(TNY_IS_MIME_PART(part))) {
1604 g_warning ("strange data in attachment list");
1605 g_object_unref (part);
1606 tny_iterator_next (att_iter);
1609 data->attachments = g_list_append (data->attachments,
1611 tny_iterator_next (att_iter);
1613 g_object_unref (att_iter);
1615 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1616 att_iter = tny_list_create_iterator (priv->images);
1617 data->images = NULL;
1618 while (!tny_iterator_is_done (att_iter)) {
1619 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1621 if (!(TNY_IS_MIME_PART(part))) {
1622 g_warning ("strange data in attachment list");
1623 g_object_unref (part);
1624 tny_iterator_next (att_iter);
1627 cid = tny_mime_part_get_content_id (part);
1629 gchar *image_tag_id;
1630 GtkTextTag *image_tag;
1632 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1633 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1634 g_free (image_tag_id);
1636 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1638 ((gtk_text_iter_has_tag (&iter, image_tag))||
1639 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1640 data->images = g_list_append (data->images,
1641 g_object_ref (part));
1643 g_object_unref (part);
1644 tny_iterator_next (att_iter);
1646 g_object_unref (att_iter);
1648 data->priority_flags = priv->priority_flags;
1655 unref_gobject (GObject *obj, gpointer data)
1657 if (!G_IS_OBJECT(obj))
1659 g_object_unref (obj);
1663 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1666 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1674 g_free (data->from);
1675 g_free (data->subject);
1676 g_free (data->plain_body);
1677 g_free (data->html_body);
1678 g_free (data->account_name);
1680 if (data->draft_msg != NULL) {
1681 g_object_unref (data->draft_msg);
1682 data->draft_msg = NULL;
1685 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1686 g_list_free (data->attachments);
1687 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1688 g_list_free (data->images);
1690 g_slice_free (MsgData, data);
1694 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1696 guint64 *parts_size)
1698 ModestMsgEditWindowPrivate *priv;
1700 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1702 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1704 /* TODO: add images */
1705 *parts_size += priv->images_size;
1706 *parts_count += priv->images_count;
1711 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1714 ModestMsgEditWindowPrivate *priv = NULL;
1715 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1717 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1719 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1721 return MODEST_MSG_EDIT_FORMAT_HTML;
1723 return MODEST_MSG_EDIT_FORMAT_TEXT;
1727 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1728 ModestMsgEditFormat format)
1730 ModestMsgEditWindowPrivate *priv;
1732 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1733 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1736 case MODEST_MSG_EDIT_FORMAT_HTML:
1737 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1739 case MODEST_MSG_EDIT_FORMAT_TEXT:
1740 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1743 g_return_if_reached ();
1747 ModestMsgEditFormatState *
1748 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1750 ModestMsgEditFormatState *format_state = NULL;
1751 ModestMsgEditWindowPrivate *priv;
1752 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1754 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1755 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1757 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1759 format_state = g_new0 (ModestMsgEditFormatState, 1);
1760 format_state->bold = buffer_format->bold&0x1;
1761 format_state->italics = buffer_format->italic&0x1;
1762 format_state->bullet = buffer_format->bullet&0x1;
1763 format_state->color = buffer_format->color;
1764 format_state->font_size = buffer_format->font_size;
1765 format_state->font_family = wp_get_font_name (buffer_format->font);
1766 format_state->justification = buffer_format->justification;
1767 g_free (buffer_format);
1769 return format_state;
1774 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1775 const ModestMsgEditFormatState *format_state)
1777 ModestMsgEditWindowPrivate *priv;
1778 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1779 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1780 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1781 g_return_if_fail (format_state != NULL);
1783 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1784 gtk_widget_grab_focus (priv->msg_body);
1785 buffer_format->bold = (format_state->bold != FALSE);
1786 buffer_format->italic = (format_state->italics != FALSE);
1787 buffer_format->color = format_state->color;
1788 buffer_format->font_size = format_state->font_size;
1789 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1790 buffer_format->justification = format_state->justification;
1791 buffer_format->bullet = format_state->bullet;
1793 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1795 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1796 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1797 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1798 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1799 buffer_format->cs.font = (buffer_format->font != current_format->font);
1800 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1801 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1803 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1804 if (buffer_format->cs.bold) {
1805 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1806 GINT_TO_POINTER (buffer_format->bold&0x1));
1808 if (buffer_format->cs.italic) {
1809 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1810 GINT_TO_POINTER (buffer_format->italic&0x1));
1812 if (buffer_format->cs.color) {
1813 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1814 GINT_TO_POINTER (&(buffer_format->color)));
1816 if (buffer_format->cs.font_size) {
1817 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1818 GINT_TO_POINTER (buffer_format->font_size));
1820 if (buffer_format->cs.justification) {
1821 switch (buffer_format->justification) {
1822 case GTK_JUSTIFY_LEFT:
1823 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1824 GINT_TO_POINTER(TRUE));
1826 case GTK_JUSTIFY_CENTER:
1827 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1828 GINT_TO_POINTER(TRUE));
1830 case GTK_JUSTIFY_RIGHT:
1831 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1832 GINT_TO_POINTER(TRUE));
1839 if (buffer_format->cs.font) {
1840 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1841 GINT_TO_POINTER (buffer_format->font));
1843 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1844 if (buffer_format->cs.bullet) {
1845 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1846 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1848 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1850 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1852 g_free (buffer_format);
1853 g_free (current_format);
1855 /* Check dimming rules */
1856 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1857 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1861 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1863 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1865 ModestWindowPrivate *parent_priv;
1866 ModestMsgEditWindowPrivate *priv;
1868 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1869 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1871 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1872 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1873 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1874 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1876 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1877 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1878 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1881 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1883 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1884 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1886 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1887 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1889 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1890 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1893 switch (buffer_format->justification)
1895 case GTK_JUSTIFY_LEFT:
1896 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1898 case GTK_JUSTIFY_CENTER:
1899 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1901 case GTK_JUSTIFY_RIGHT:
1902 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1909 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1911 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1912 G_CALLBACK (modest_msg_edit_window_color_button_change),
1914 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1915 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1916 G_CALLBACK (modest_msg_edit_window_color_button_change),
1919 if (priv->current_size_index != buffer_format->font_size) {
1923 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
1924 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
1928 priv->current_size_index = buffer_format->font_size;
1930 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
1931 markup = g_strconcat ("<span font_family='Sans'>",
1932 size_text, "</span>", NULL);
1934 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1938 gtk_tree_path_free (path);
1941 if (priv->current_face_index != buffer_format->font) {
1945 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
1946 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
1950 priv->current_face_index = buffer_format->font;
1951 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
1952 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
1953 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1960 g_free (buffer_format);
1964 #ifdef MODEST_HILDON_VERSION_0
1966 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1969 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1970 ModestMsgEditWindowPrivate *priv;
1971 GtkWidget *dialog = NULL;
1973 GdkColor *new_color = NULL;
1975 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1976 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1978 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1979 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1980 g_free (buffer_format);
1982 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
1983 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1984 if (new_color != NULL) {
1985 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1986 (gpointer) new_color);
1989 gtk_widget_destroy (dialog);
1994 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1997 ModestMsgEditWindowPrivate *priv;
1998 GtkWidget *dialog = NULL;
2000 GdkColor *old_color = NULL;
2001 const GdkColor *new_color = NULL;
2003 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2004 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2006 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2007 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2009 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2010 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2011 if (new_color != NULL)
2012 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2014 gtk_widget_destroy (dialog);
2020 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2023 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2024 ModestMsgEditWindowPrivate *priv;
2025 GtkWidget *dialog = NULL;
2027 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2028 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2030 dialog = hildon_color_chooser_new ();
2031 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2032 g_free (buffer_format);
2034 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2036 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2037 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2040 gtk_widget_destroy (dialog);
2045 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2048 ModestMsgEditWindowPrivate *priv;
2049 GtkWidget *dialog = NULL;
2050 GdkColor *old_color = NULL;
2052 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2053 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2055 dialog = hildon_color_chooser_new ();
2056 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2058 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2060 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2061 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2063 gtk_widget_destroy (dialog);
2066 #endif /*!MODEST_HILDON_VERSION_0*/
2071 create_stream_for_uri (const gchar* uri)
2076 TnyStream *result = NULL;
2078 GnomeVFSHandle *handle = NULL;
2079 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2080 if (test == GNOME_VFS_OK) {
2081 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2082 /* Streams over OBEX (Bluetooth) are not seekable but
2083 * we expect them to be (we might need to read them
2084 * several times). So if this is a Bluetooth URI just
2085 * read the whole file into memory (this is not a fast
2086 * protocol so we can assume that these files are not
2087 * going to be very big) */
2088 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2089 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2090 TnyStream *memstream = tny_camel_mem_stream_new ();
2091 tny_stream_write_to_stream (vfssstream, memstream);
2092 g_object_unref (vfssstream);
2095 result = vfssstream;
2103 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2106 ModestMsgEditWindowPrivate *priv;
2107 GtkWidget *dialog = NULL;
2109 GSList *uris = NULL;
2110 GSList *uri_node = NULL;
2112 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2114 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2115 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2116 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2118 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2120 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2121 GTK_WINDOW (dialog), GTK_WINDOW (window));
2123 response = gtk_dialog_run (GTK_DIALOG (dialog));
2125 case GTK_RESPONSE_OK:
2126 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2131 gtk_widget_destroy (dialog);
2133 g_object_ref (window);
2134 /* The operation could take some time so allow the dialog to be closed */
2135 while (gtk_events_pending ())
2136 gtk_main_iteration ();
2138 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2140 GnomeVFSHandle *handle = NULL;
2141 GnomeVFSResult result;
2142 GtkTextIter position;
2143 GtkTextMark *insert_mark;
2145 uri = (const gchar *) uri_node->data;
2146 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2147 if (result == GNOME_VFS_OK) {
2149 GnomeVFSFileInfo *info;
2150 gchar *filename, *basename, *escaped_filename;
2151 TnyMimePart *mime_part;
2153 const gchar *mime_type = NULL;
2154 GnomeVFSURI *vfs_uri;
2155 guint64 stream_size;
2157 gnome_vfs_close (handle);
2158 vfs_uri = gnome_vfs_uri_new (uri);
2160 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2161 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2162 g_free (escaped_filename);
2163 gnome_vfs_uri_unref (vfs_uri);
2164 info = gnome_vfs_file_info_new ();
2166 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2167 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2169 mime_type = gnome_vfs_file_info_get_mime_type (info);
2171 mime_part = tny_platform_factory_new_mime_part
2172 (modest_runtime_get_platform_factory ());
2174 TnyStream *stream = create_stream_for_uri (uri);
2176 if (stream == NULL) {
2178 modest_platform_information_banner (NULL, NULL,
2179 _FM("sfil_ib_opening_not_allowed"));
2181 g_object_unref (mime_part);
2182 gnome_vfs_file_info_unref (info);
2186 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2188 content_id = g_strdup_printf ("%d", priv->next_cid);
2189 tny_mime_part_set_content_id (mime_part, content_id);
2190 g_free (content_id);
2193 basename = g_path_get_basename (filename);
2194 tny_mime_part_set_filename (mime_part, basename);
2197 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2199 if (pixbuf != NULL) {
2200 priv->images_size += stream_size;
2201 priv->images_count ++;
2202 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2203 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2204 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2205 tny_mime_part_get_content_id (mime_part), pixbuf);
2206 g_object_unref (pixbuf);
2208 tny_list_prepend (priv->images, (GObject *) mime_part);
2209 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2211 modest_platform_information_banner (NULL, NULL,
2212 _("mail_ib_file_operation_failed"));
2216 g_object_unref (mime_part);
2217 gnome_vfs_file_info_unref (info);
2221 g_object_unref (window);
2225 on_attach_file_response (GtkDialog *dialog,
2229 GSList *uris = NULL;
2231 GnomeVFSFileSize total_size, allowed_size;
2232 ModestMsgEditWindow *window;
2233 ModestMsgEditWindowPrivate *priv;
2238 case GTK_RESPONSE_OK:
2239 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2245 window = MODEST_MSG_EDIT_WINDOW (user_data);
2246 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2248 /* allowed size is the maximum size - what's already there */
2249 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2250 &att_num, &att_size);
2251 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2254 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2256 const gchar *uri = (const gchar *) uri_node->data;
2259 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2261 if (total_size > allowed_size) {
2262 g_warning ("%s: total size: %u",
2263 __FUNCTION__, (unsigned int)total_size);
2266 allowed_size -= total_size;
2268 g_slist_foreach (uris, (GFunc) g_free, NULL);
2269 g_slist_free (uris);
2271 gtk_widget_destroy (GTK_WIDGET (dialog));
2275 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2277 GtkWidget *dialog = NULL;
2278 ModestMsgEditWindowPrivate *priv;
2280 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2282 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2284 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2287 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2288 GTK_FILE_CHOOSER_ACTION_OPEN);
2289 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2290 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2291 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2292 GTK_WINDOW (dialog), GTK_WINDOW (window));
2294 /* Connect to response & show */
2295 g_signal_connect (dialog, "response",
2296 G_CALLBACK (on_attach_file_response), window);
2297 gtk_widget_show (dialog);
2302 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2304 GnomeVFSFileSize allowed_size)
2307 GnomeVFSHandle *handle = NULL;
2308 ModestMsgEditWindowPrivate *priv;
2309 GnomeVFSResult result;
2310 GnomeVFSFileSize size = 0;
2311 g_return_val_if_fail (window, 0);
2312 g_return_val_if_fail (uri, 0);
2314 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2316 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2317 if (result == GNOME_VFS_OK) {
2318 TnyMimePart *mime_part;
2320 const gchar *mime_type = NULL;
2322 gchar *escaped_filename;
2325 GnomeVFSFileInfo *info;
2326 GnomeVFSURI *vfs_uri;
2328 gnome_vfs_close (handle);
2329 vfs_uri = gnome_vfs_uri_new (uri);
2332 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2333 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2334 g_free (escaped_filename);
2335 gnome_vfs_uri_unref (vfs_uri);
2337 info = gnome_vfs_file_info_new ();
2339 if (gnome_vfs_get_file_info (uri,
2341 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2343 mime_type = gnome_vfs_file_info_get_mime_type (info);
2344 mime_part = tny_platform_factory_new_mime_part
2345 (modest_runtime_get_platform_factory ());
2347 /* try to get the attachment's size; this may fail for weird
2348 * file systems, like obex, upnp... */
2349 if (allowed_size != 0 &&
2350 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2352 if (size > allowed_size) {
2353 modest_platform_information_banner (NULL, NULL,
2354 _FM("sfil_ib_opening_not_allowed"));
2359 g_warning ("%s: could not get attachment size", __FUNCTION__);
2361 stream = create_stream_for_uri (uri);
2363 if (stream == NULL) {
2365 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2367 g_object_unref (mime_part);
2369 gnome_vfs_file_info_unref (info);
2373 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2374 g_object_unref (stream);
2376 content_id = g_strdup_printf ("%d", priv->next_cid);
2377 tny_mime_part_set_content_id (mime_part, content_id);
2378 g_free (content_id);
2381 basename = g_path_get_basename (filename);
2382 tny_mime_part_set_filename (mime_part, basename);
2385 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2386 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2388 info->size == 0, info->size);
2389 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2390 gtk_widget_show_all (priv->attachments_caption);
2391 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2393 g_object_unref (mime_part);
2394 gnome_vfs_file_info_unref (info);
2401 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2404 ModestMsgEditWindowPrivate *priv;
2407 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2408 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2410 if (att_list == NULL) {
2411 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2412 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2413 g_object_unref (att_list);
2418 g_object_ref (att_list);
2421 if (tny_list_get_length (att_list) == 0) {
2422 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2424 gboolean dialog_response;
2425 gchar *message = NULL;
2426 gchar *filename = NULL;
2428 if (tny_list_get_length (att_list) == 1) {
2430 iter = tny_list_create_iterator (att_list);
2431 part = (TnyMimePart *) tny_iterator_get_current (iter);
2432 g_object_unref (iter);
2433 if (TNY_IS_MSG (part)) {
2434 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2436 filename = tny_header_dup_subject (header);
2437 g_object_unref (header);
2439 if (filename == NULL) {
2440 filename = g_strdup (_("mail_va_no_subject"));
2443 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2445 g_object_unref (part);
2447 filename = g_strdup ("");
2449 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2450 "emev_nc_delete_attachments",
2451 tny_list_get_length (att_list)), filename);
2454 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2458 if (dialog_response != GTK_RESPONSE_OK) {
2459 g_object_unref (att_list);
2463 for (iter = tny_list_create_iterator (att_list);
2464 !tny_iterator_is_done (iter);
2465 tny_iterator_next (iter)) {
2466 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2467 const gchar *att_id;
2468 tny_list_remove (priv->attachments, (GObject *) mime_part);
2470 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2472 if (tny_list_get_length (priv->attachments) == 0)
2473 gtk_widget_hide (priv->attachments_caption);
2474 att_id = tny_mime_part_get_content_id (mime_part);
2476 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2478 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2479 g_object_unref (mime_part);
2481 g_object_unref (iter);
2484 g_object_unref (att_list);
2486 /* if the last attachment has been removed, focus the Subject: field */
2487 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2488 gtk_widget_grab_focus (priv->subject_field);
2492 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2495 ModestMsgEditWindowPrivate *priv;
2496 GdkColor *new_color;
2497 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2499 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2500 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2503 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2505 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2507 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2509 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2514 font_size_clicked (GtkToolButton *button,
2515 ModestMsgEditWindow *window)
2517 ModestMsgEditWindowPrivate *priv;
2518 GtkWidget *selector, *dialog;
2520 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2522 selector = hildon_touch_selector_new ();
2523 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2524 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2526 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2527 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2529 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2533 WPTextBufferFormat format;
2535 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2537 memset (&format, 0, sizeof (format));
2538 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2540 format.cs.font_size = TRUE;
2541 format.cs.text_position = TRUE;
2542 format.cs.font = TRUE;
2543 format.font_size = new_index;
2544 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2546 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2547 GINT_TO_POINTER (new_index)))
2548 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2550 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2551 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2552 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2553 size_text, "</span>", NULL);
2555 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2559 gtk_widget_destroy (dialog);
2561 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2566 font_face_clicked (GtkToolButton *button,
2567 ModestMsgEditWindow *window)
2569 ModestMsgEditWindowPrivate *priv;
2570 GtkWidget *selector, *dialog;
2571 GtkCellRenderer *renderer;
2573 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2575 selector = hildon_touch_selector_new ();
2576 renderer = gtk_cell_renderer_text_new ();
2577 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2578 renderer, "family", 0, "text", 0, NULL);
2579 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2581 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2582 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2584 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2585 gint new_font_index;
2589 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2590 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2591 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2595 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2597 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2598 GINT_TO_POINTER(new_font_index)))
2599 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2601 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2602 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2604 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2608 gtk_tree_path_free (path);
2611 gtk_widget_destroy (dialog);
2613 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2618 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2621 ModestMsgEditWindowPrivate *priv = NULL;
2622 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2624 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2625 if (!priv->update_caption_visibility)
2628 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2630 gtk_widget_show (priv->cc_caption);
2632 gtk_widget_hide (priv->cc_caption);
2634 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2638 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2641 ModestMsgEditWindowPrivate *priv = NULL;
2642 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2644 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2645 if (!priv->update_caption_visibility)
2648 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2650 gtk_widget_show (priv->bcc_caption);
2652 gtk_widget_hide (priv->bcc_caption);
2654 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2658 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2659 ModestRecptEditor *editor)
2661 ModestMsgEditWindowPrivate *priv;
2663 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2664 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2666 /* we check for low-mem; in that case, show a warning, and don't allow
2667 * for the addressbook
2669 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2672 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2674 if (editor == NULL) {
2675 GtkWidget *view_focus;
2676 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2678 /* This code should be kept in sync with ModestRecptEditor. The
2679 textview inside the recpt editor is the one that really gets the
2680 focus. As it's inside a scrolled window, and this one inside the
2681 hbox recpt editor inherits from, we'll need to go up in the
2682 hierarchy to know if the text view is part of the recpt editor
2683 or if it's a different text entry */
2685 if (gtk_widget_get_parent (view_focus)) {
2686 GtkWidget *first_parent;
2688 first_parent = gtk_widget_get_parent (view_focus);
2689 if (gtk_widget_get_parent (first_parent) &&
2690 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2691 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2696 editor = MODEST_RECPT_EDITOR (priv->to_field);
2700 modest_address_book_select_addresses (editor);
2705 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2707 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2709 modest_msg_edit_window_open_addressbook (window, NULL);
2713 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2714 gboolean show_toolbar)
2716 ModestWindowPrivate *parent_priv;
2718 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2719 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2721 /* We can not just use the code of
2722 modest_msg_edit_window_setup_toolbar because it has a
2723 mixture of both initialization and creation code. */
2725 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2727 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2731 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2732 TnyHeaderFlags priority_flags)
2734 ModestMsgEditWindowPrivate *priv;
2735 ModestWindowPrivate *parent_priv;
2737 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2739 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2740 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2742 if (priv->priority_flags != priority_flags) {
2743 GtkAction *priority_action = NULL;
2745 priv->priority_flags = priority_flags;
2747 switch (priority_flags) {
2748 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2749 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2750 MODEST_HEADER_ICON_HIGH,
2751 HILDON_ICON_SIZE_SMALL);
2752 gtk_widget_show (priv->priority_icon);
2753 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2754 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2756 case TNY_HEADER_FLAG_LOW_PRIORITY:
2757 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2758 MODEST_HEADER_ICON_LOW,
2759 HILDON_ICON_SIZE_SMALL);
2760 gtk_widget_show (priv->priority_icon);
2761 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2762 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2765 gtk_widget_hide (priv->priority_icon);
2766 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2767 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2770 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2771 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2773 gtk_widget_queue_resize (priv->subject_box);
2777 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2780 ModestMsgEditWindowPrivate *priv;
2781 ModestWindowPrivate *parent_priv;
2782 gint current_format;
2784 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2786 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2787 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2789 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2790 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2792 if (current_format != file_format) {
2793 switch (file_format) {
2794 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2795 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2796 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2798 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2802 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2803 response = gtk_dialog_run (GTK_DIALOG (dialog));
2804 gtk_widget_destroy (dialog);
2805 if (response == GTK_RESPONSE_OK) {
2806 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2808 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2809 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2814 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2815 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2816 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2821 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2824 ModestMsgEditWindowPrivate *priv;
2825 WPTextBufferFormat oldfmt, fmt;
2826 gint old_position = 0;
2830 GdkColor *color = NULL;
2831 gboolean bold, bold_set, italic, italic_set;
2832 gboolean underline, underline_set;
2833 gboolean strikethrough, strikethrough_set;
2834 gboolean position_set;
2835 gboolean font_size_set, font_set, color_set;
2838 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2839 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2841 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2842 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2843 GTK_WINDOW(dialog), GTK_WINDOW (window));
2845 /* First we get the currently selected font information */
2846 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2848 switch (oldfmt.text_position) {
2849 case TEXT_POSITION_NORMAL:
2852 case TEXT_POSITION_SUPERSCRIPT:
2860 g_object_set (G_OBJECT (dialog),
2861 "bold", oldfmt.bold != FALSE,
2862 "bold-set", !oldfmt.cs.bold,
2863 "underline", oldfmt.underline != FALSE,
2864 "underline-set", !oldfmt.cs.underline,
2865 "italic", oldfmt.italic != FALSE,
2866 "italic-set", !oldfmt.cs.italic,
2867 "strikethrough", oldfmt.strikethrough != FALSE,
2868 "strikethrough-set", !oldfmt.cs.strikethrough,
2869 "color", &oldfmt.color,
2870 "color-set", !oldfmt.cs.color,
2871 "size", wp_font_size[oldfmt.font_size],
2872 "size-set", !oldfmt.cs.font_size,
2873 "position", old_position,
2874 "position-set", !oldfmt.cs.text_position,
2875 "family", wp_get_font_name (oldfmt.font),
2876 "family-set", !oldfmt.cs.font,
2879 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2880 GTK_WINDOW (dialog), GTK_WINDOW (window));
2881 gtk_widget_show_all (dialog);
2882 priv->font_dialog = dialog;
2883 response = gtk_dialog_run (GTK_DIALOG (dialog));
2884 priv->font_dialog = NULL;
2885 if (response == GTK_RESPONSE_OK) {
2887 g_object_get( dialog,
2889 "bold-set", &bold_set,
2890 "underline", &underline,
2891 "underline-set", &underline_set,
2893 "italic-set", &italic_set,
2894 "strikethrough", &strikethrough,
2895 "strikethrough-set", &strikethrough_set,
2897 "color-set", &color_set,
2899 "size-set", &font_size_set,
2900 "family", &font_name,
2901 "family-set", &font_set,
2902 "position", &position,
2903 "position-set", &position_set,
2908 if (response == GTK_RESPONSE_OK) {
2909 memset(&fmt, 0, sizeof(fmt));
2915 fmt.italic = italic;
2916 fmt.cs.italic = TRUE;
2918 if (underline_set) {
2919 fmt.underline = underline;
2920 fmt.cs.underline = TRUE;
2922 if (strikethrough_set) {
2923 fmt.strikethrough = strikethrough;
2924 fmt.cs.strikethrough = TRUE;
2929 ? TEXT_POSITION_NORMAL
2930 : ( ( position == 1 )
2931 ? TEXT_POSITION_SUPERSCRIPT
2932 : TEXT_POSITION_SUBSCRIPT );
2933 fmt.cs.text_position = TRUE;
2934 fmt.font_size = oldfmt.font_size;
2938 fmt.cs.color = TRUE;
2941 fmt.font = wp_get_font_index(font_name,
2946 if (font_size_set) {
2947 fmt.cs.font_size = TRUE;
2948 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2950 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2951 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2953 gtk_widget_destroy (dialog);
2955 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2959 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2961 ModestMsgEditWindowPrivate *priv;
2963 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2964 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2966 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2968 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2969 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2973 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2975 ModestMsgEditWindowPrivate *priv;
2977 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2978 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2980 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2982 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2983 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2988 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2990 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2992 priv->can_undo = can_undo;
2996 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2998 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3000 priv->can_redo = can_redo;
3004 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3006 ModestMsgEditWindowPrivate *priv;
3007 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3008 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3010 return priv->can_undo;
3014 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3016 ModestMsgEditWindowPrivate *priv;
3017 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3018 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3020 return priv->can_redo;
3025 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3028 GtkTextIter match_start, match_end;
3030 if (image_id == NULL)
3033 gtk_text_buffer_get_start_iter (buffer, &iter);
3035 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3036 GSList *tags = gtk_text_iter_get_tags (&match_start);
3038 for (node = tags; node != NULL; node = g_slist_next (node)) {
3039 GtkTextTag *tag = (GtkTextTag *) node->data;
3040 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3041 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3042 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3044 offset = gtk_text_iter_get_offset (&match_start);
3045 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3046 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3050 gtk_text_iter_forward_char (&iter);
3055 message_is_empty (ModestMsgEditWindow *window)
3057 ModestMsgEditWindowPrivate *priv = NULL;
3059 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3060 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3062 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3063 * so we can ignore markup.
3065 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3068 count = gtk_text_buffer_get_char_count (buf);
3074 msg_body_focus (GtkWidget *focus,
3075 GdkEventFocus *event,
3079 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3080 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3081 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3086 recpt_field_changed (GtkTextBuffer *buffer,
3087 ModestMsgEditWindow *editor)
3089 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3090 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3094 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3096 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3097 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3101 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3104 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3105 GtkTextBuffer *buffer;
3107 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3108 gtk_text_buffer_set_modified (buffer, modified);
3109 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3110 gtk_text_buffer_set_modified (buffer, modified);
3111 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3112 gtk_text_buffer_set_modified (buffer, modified);
3113 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3117 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3119 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3120 const char *account_name;
3121 GtkTextBuffer *buffer;
3123 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3124 if (gtk_text_buffer_get_modified (buffer))
3126 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3127 if (gtk_text_buffer_get_modified (buffer))
3129 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3130 if (gtk_text_buffer_get_modified (buffer))
3132 if (gtk_text_buffer_get_modified (priv->text_buffer))
3134 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3135 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3146 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3148 ModestMsgEditWindowPrivate *priv = NULL;
3150 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3151 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3153 /* check if there's no recipient added */
3154 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3155 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3156 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3157 /* no recipient contents, then select contacts */
3158 modest_msg_edit_window_open_addressbook (window, NULL);
3162 g_object_ref (window);
3163 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3164 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3165 g_object_unref (window);
3168 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3169 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3170 g_object_unref (window);
3173 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3174 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3175 g_object_unref (window);
3179 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3180 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3181 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3182 g_object_unref (window);
3189 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3190 ModestMsgEditWindow *window)
3192 modest_msg_edit_window_offer_attach_file (window);
3196 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3198 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3200 return priv->clipboard_text;
3204 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3206 ModestMsgEditWindow *window)
3208 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3209 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3211 if (!GTK_WIDGET_VISIBLE (window))
3214 g_object_ref (window);
3215 text = gtk_clipboard_wait_for_text (selection_clipboard);
3217 if (priv->clipboard_text != NULL) {
3218 g_free (priv->clipboard_text);
3220 priv->clipboard_text = text;
3222 if (GTK_WIDGET_VISIBLE (window)) {
3223 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3225 g_object_unref (window);
3228 static gboolean clipboard_owner_change_idle (gpointer userdata)
3230 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3231 ModestMsgEditWindowPrivate *priv;
3233 gdk_threads_enter ();
3234 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3235 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3237 priv->clipboard_owner_idle = 0;
3238 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3239 gdk_threads_leave ();
3245 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3247 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3248 if (priv->clipboard_owner_idle == 0) {
3249 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3254 subject_field_move_cursor (GtkEntry *entry,
3255 GtkMovementStep step,
3260 if (!GTK_WIDGET_VISIBLE (window))
3263 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3267 update_window_title (ModestMsgEditWindow *window)
3269 ModestMsgEditWindowPrivate *priv = NULL;
3270 const gchar *subject;
3272 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3273 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3274 if (subject == NULL || subject[0] == '\0')
3275 subject = _("mail_va_new_email");
3277 gtk_window_set_title (GTK_WINDOW (window), subject);
3282 subject_field_changed (GtkEditable *editable,
3283 ModestMsgEditWindow *window)
3285 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3286 update_window_title (window);
3287 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3288 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3289 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3293 subject_field_insert_text (GtkEditable *editable,
3295 gint new_text_length,
3297 ModestMsgEditWindow *window)
3299 GString *result = g_string_new ("");
3301 gint result_len = 0;
3302 const gchar *entry_text = NULL;
3305 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3306 old_length = g_utf8_strlen (entry_text, -1);
3308 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3309 gunichar c = g_utf8_get_char_validated (current, 8);
3310 /* Invalid unichar, stop */
3316 result = g_string_append_unichar (result, c);
3320 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3321 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3324 /* Prevent endless recursion */
3325 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3326 g_signal_emit_by_name (editable, "insert-text",
3327 (gpointer) result->str, (gpointer) result->len,
3328 (gpointer) position, (gpointer) window);
3329 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3333 if (result_len + old_length > 1000) {
3334 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3335 _CS("ckdg_ib_maximum_characters_reached"));
3337 g_string_free (result, TRUE);
3341 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3344 ModestMsgEditWindowPrivate *priv = NULL;
3346 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3347 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3349 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3352 gtk_widget_show_all (priv->find_toolbar);
3353 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3355 gtk_widget_hide_all (priv->find_toolbar);
3356 gtk_widget_grab_focus (priv->msg_body);
3361 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3363 GtkTextIter *match_start,
3364 GtkTextIter *match_end)
3366 GtkTextIter end_iter;
3367 gchar *str_casefold;
3370 gchar *range_casefold;
3373 gboolean result = FALSE;
3380 gtk_text_iter_forward_to_end (&end_iter);
3382 str_casefold = g_utf8_casefold (str, -1);
3383 str_chars_n = strlen (str);
3385 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3386 range_casefold = g_utf8_casefold (range_text, -1);
3387 range_chars_n = strlen (range_casefold);
3389 if (range_chars_n < str_chars_n) {
3390 g_free (str_casefold);
3391 g_free (range_text);
3392 g_free (range_casefold);
3396 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3397 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3398 if (!g_utf8_collate (range_subtext, str_casefold)) {
3399 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3401 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3402 match_start, match_end, NULL);
3403 g_free (found_text);
3405 g_free (range_subtext);
3409 g_free (str_casefold);
3410 g_free (range_text);
3411 g_free (range_casefold);
3418 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3419 ModestMsgEditWindow *window)
3421 gchar *current_search = NULL;
3422 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3424 GtkTextIter selection_start, selection_end;
3425 GtkTextIter match_start, match_end;
3426 gboolean continue_search = FALSE;
3428 if (message_is_empty (window)) {
3429 g_free (priv->last_search);
3430 priv->last_search = NULL;
3431 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3435 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3436 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3437 g_free (current_search);
3438 g_free (priv->last_search);
3439 priv->last_search = NULL;
3440 /* Information banner about empty search */
3441 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3445 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3446 continue_search = TRUE;
3448 g_free (priv->last_search);
3449 priv->last_search = g_strdup (current_search);
3452 if (continue_search) {
3453 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3454 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3455 &match_start, &match_end);
3457 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3459 GtkTextIter buffer_start;
3460 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3461 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3462 &match_start, &match_end);
3464 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3467 /* Mark as selected the string found in search */
3469 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3470 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3471 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3473 g_free (priv->last_search);
3474 priv->last_search = NULL;
3476 g_free (current_search);
3480 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3482 ModestMsgEditWindowPrivate *priv;
3484 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3489 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3492 ModestMsgEditWindowPrivate *priv;
3494 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3499 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3500 ModestMsgEditWindow *window)
3502 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3506 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3509 ModestMsgEditWindowPrivate *priv;
3510 TnyHeader *header = NULL;
3512 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3513 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3515 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3516 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3518 if (priv->draft_msg != NULL) {
3519 g_object_unref (priv->draft_msg);
3522 if (draft != NULL) {
3523 g_object_ref (draft);
3524 header = tny_msg_get_header (draft);
3525 if (priv->msg_uid) {
3526 g_free (priv->msg_uid);
3527 priv->msg_uid = NULL;
3529 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3530 if (GTK_WIDGET_REALIZED (window)) {
3531 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3532 gtk_widget_destroy (GTK_WIDGET (window));
3538 priv->draft_msg = draft;
3542 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3543 GtkTextIter *start, GtkTextIter *end,
3546 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3547 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3550 if (tag == NULL) return;
3551 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3552 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3553 replace_with_images (window, priv->images);
3558 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3561 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3563 g_return_if_fail (TNY_IS_MIME_PART (part));
3564 tny_list_prepend (priv->attachments, (GObject *) part);
3565 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3566 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3567 gtk_widget_show_all (priv->attachments_caption);
3568 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3572 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3574 ModestMsgEditWindowPrivate *priv;
3576 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3577 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3579 return priv->msg_uid;
3583 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3584 ModestMsgEditWindowWidgetType widget_type)
3586 ModestMsgEditWindowPrivate *priv;
3588 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3589 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3591 switch (widget_type) {
3592 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3593 return priv->msg_body;
3595 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3596 return priv->to_field;
3598 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3599 return priv->cc_field;
3601 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3602 return priv->bcc_field;
3604 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3605 return priv->subject_field;
3607 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3608 return priv->attachments_view;
3616 remove_tags (WPTextBuffer *buffer)
3618 GtkTextIter start, end;
3620 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3621 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3623 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3627 on_account_removed (TnyAccountStore *account_store,
3628 TnyAccount *account,
3631 /* Do nothing if it's a store account, because we use the
3632 transport to send the messages */
3633 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3634 const gchar *parent_acc = NULL;
3635 const gchar *our_acc = NULL;
3637 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3638 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3639 /* Close this window if I'm showing a message of the removed account */
3640 if (strcmp (parent_acc, our_acc) == 0)
3641 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3646 from_field_changed (HildonPickerButton *button,
3647 ModestMsgEditWindow *self)
3649 ModestMsgEditWindowPrivate *priv;
3650 gboolean has_old_signature, has_new_signature;
3652 GtkTextIter match_start, match_end;
3653 ModestAccountMgr *mgr;
3655 gchar *full_signature;
3657 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3659 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3660 mgr = modest_runtime_get_account_mgr ();
3661 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3662 if (has_old_signature) {
3663 full_signature = g_strconcat ("\n--\n", signature, NULL);
3664 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3665 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3667 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3668 &match_start, &match_end, NULL)) {
3671 g_free (full_signature);
3675 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3676 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3677 if (has_new_signature) {
3678 full_signature = g_strconcat ("\n--\n", signature, NULL);
3679 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3680 g_free (full_signature);
3685 typedef struct _MessageSettingsHelper {
3686 ModestMsgEditWindow *window;
3687 GSList *priority_group;
3688 GSList *format_group;
3689 GtkToggleButton *current_priority;
3690 GtkToggleButton *current_format;
3691 } MessageSettingsHelper;
3694 on_priority_toggle (GtkToggleButton *button,
3695 MessageSettingsHelper *helper)
3698 ModestMsgEditWindowPrivate *priv;
3700 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3701 if (gtk_toggle_button_get_active (button)) {
3703 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3704 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3705 if ((node_button != button) &&
3706 gtk_toggle_button_get_active (node_button)) {
3707 gtk_toggle_button_set_active (node_button, FALSE);
3710 helper->current_priority = button;
3712 gboolean found = FALSE;
3713 /* If no one is active, activate it again */
3714 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3715 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3716 if (gtk_toggle_button_get_active (node_button)) {
3722 gtk_toggle_button_set_active (button, TRUE);
3728 on_format_toggle (GtkToggleButton *button,
3729 MessageSettingsHelper *helper)
3732 ModestMsgEditWindowPrivate *priv;
3734 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3735 if (gtk_toggle_button_get_active (button)) {
3737 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3738 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3739 if ((node_button != button) &&
3740 gtk_toggle_button_get_active (node_button)) {
3741 gtk_toggle_button_set_active (node_button, FALSE);
3744 helper->current_format = button;
3746 gboolean found = FALSE;
3747 /* If no one is active, activate it again */
3748 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3749 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3750 if (gtk_toggle_button_get_active (node_button)) {
3756 gtk_toggle_button_set_active (button, TRUE);
3763 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3768 GtkWidget *priority_hbox;
3769 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3770 GtkWidget *captioned;
3771 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3772 GtkWidget *format_hbox;
3773 GtkWidget *html_toggle, *text_toggle;
3774 ModestMsgEditWindowPrivate *priv;
3775 MessageSettingsHelper helper = {0,};
3777 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3778 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3779 helper.window = window;
3780 helper.priority_group = NULL;
3781 helper.format_group = NULL;
3783 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3784 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3786 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3787 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3788 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3789 vbox = gtk_vbox_new (FALSE, 0);
3790 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
3791 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
3792 gtk_container_add (GTK_CONTAINER (align), vbox);
3793 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
3794 gtk_widget_show (align);
3795 gtk_widget_show (vbox);
3797 /* Priority toggles */
3798 priority_hbox = gtk_hbox_new (TRUE, 0);
3799 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3800 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3801 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3802 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3803 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3804 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3805 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3806 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3807 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3808 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3809 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3810 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3811 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3812 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3813 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3814 gtk_widget_show_all (priority_hbox);
3815 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3816 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3817 gtk_widget_show (captioned);
3818 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3820 /* format toggles */
3821 format_hbox = gtk_hbox_new (TRUE, 0);
3822 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3823 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3824 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3825 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3826 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3827 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3828 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3829 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3830 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3831 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3832 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3833 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3834 gtk_widget_show_all (format_hbox);
3835 gtk_widget_show (format_hbox);
3836 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3839 g_object_unref (title_sizegroup);
3840 g_object_unref (value_sizegroup);
3842 /* Set current values */
3843 switch (priv->priority_flags) {
3844 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3845 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3846 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3848 case TNY_HEADER_FLAG_LOW_PRIORITY:
3849 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3850 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3853 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3854 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3858 switch (modest_msg_edit_window_get_format (window)) {
3859 case MODEST_MSG_EDIT_FORMAT_TEXT:
3860 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3861 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3863 case MODEST_MSG_EDIT_FORMAT_HTML:
3865 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3866 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3870 /* Signal connects */
3871 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3872 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3873 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3874 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3875 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3877 /* Save settings if the user clicked on done */
3878 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3879 TnyHeaderFlags flags;
3880 ModestMsgEditFormat old_format, new_format;
3882 /* Set priority flags */
3883 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3884 if (priv->priority_flags != flags)
3885 modest_msg_edit_window_set_priority_flags (window, flags);
3887 /* Set edit format */
3888 old_format = modest_msg_edit_window_get_format (window);
3889 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3890 if (old_format != new_format) {
3891 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3892 modest_msg_edit_window_set_file_format (window, file_format);
3896 gtk_widget_destroy (dialog);
3897 g_slist_free (helper.priority_group);
3901 on_message_settings (GtkAction *action,
3902 ModestMsgEditWindow *window)
3904 modest_msg_edit_window_show_msg_settings_dialog (window);
3908 on_cc_button_toggled (HildonCheckButton *button,
3909 ModestMsgEditWindow *window)
3911 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3913 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3914 hildon_check_button_get_active (button));
3918 on_bcc_button_toggled (HildonCheckButton *button,
3919 ModestMsgEditWindow *window)
3921 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3923 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3924 hildon_check_button_get_active (button));
3928 setup_menu (ModestMsgEditWindow *self)
3930 ModestMsgEditWindowPrivate *priv = NULL;
3932 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3934 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3936 /* Settings menu buttons */
3937 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3938 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3940 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3941 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3942 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3944 priv->cc_button = hildon_check_button_new (0);
3945 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3946 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3948 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3950 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3951 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3952 priv->bcc_button = hildon_check_button_new (0);
3953 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3954 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3956 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3958 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3959 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3961 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3962 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3963 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3964 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3965 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3966 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3967 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3968 APP_MENU_CALLBACK (on_message_settings),
3970 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3971 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),