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"));
2358 g_warning ("%s: could not get attachment size", __FUNCTION__);
2360 stream = create_stream_for_uri (uri);
2362 if (stream == NULL) {
2364 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2366 g_object_unref (mime_part);
2367 gnome_vfs_file_info_unref (info);
2371 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2372 g_object_unref (stream);
2374 content_id = g_strdup_printf ("%d", priv->next_cid);
2375 tny_mime_part_set_content_id (mime_part, content_id);
2376 g_free (content_id);
2379 basename = g_path_get_basename (filename);
2380 tny_mime_part_set_filename (mime_part, basename);
2383 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2384 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2386 info->size == 0, info->size);
2387 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2388 gtk_widget_show_all (priv->attachments_caption);
2389 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2391 g_object_unref (mime_part);
2392 gnome_vfs_file_info_unref (info);
2399 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2402 ModestMsgEditWindowPrivate *priv;
2405 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2406 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2408 if (att_list == NULL) {
2409 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2410 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2411 g_object_unref (att_list);
2416 g_object_ref (att_list);
2419 if (tny_list_get_length (att_list) == 0) {
2420 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2422 gboolean dialog_response;
2423 gchar *message = NULL;
2424 gchar *filename = NULL;
2426 if (tny_list_get_length (att_list) == 1) {
2428 iter = tny_list_create_iterator (att_list);
2429 part = (TnyMimePart *) tny_iterator_get_current (iter);
2430 g_object_unref (iter);
2431 if (TNY_IS_MSG (part)) {
2432 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2434 filename = tny_header_dup_subject (header);
2435 g_object_unref (header);
2437 if (filename == NULL) {
2438 filename = g_strdup (_("mail_va_no_subject"));
2441 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2443 g_object_unref (part);
2445 filename = g_strdup ("");
2447 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2448 "emev_nc_delete_attachments",
2449 tny_list_get_length (att_list)), filename);
2452 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2456 if (dialog_response != GTK_RESPONSE_OK) {
2457 g_object_unref (att_list);
2461 for (iter = tny_list_create_iterator (att_list);
2462 !tny_iterator_is_done (iter);
2463 tny_iterator_next (iter)) {
2464 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2465 const gchar *att_id;
2466 tny_list_remove (priv->attachments, (GObject *) mime_part);
2468 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2470 if (tny_list_get_length (priv->attachments) == 0)
2471 gtk_widget_hide (priv->attachments_caption);
2472 att_id = tny_mime_part_get_content_id (mime_part);
2474 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2476 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2477 g_object_unref (mime_part);
2479 g_object_unref (iter);
2482 g_object_unref (att_list);
2484 /* if the last attachment has been removed, focus the Subject: field */
2485 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2486 gtk_widget_grab_focus (priv->subject_field);
2490 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2493 ModestMsgEditWindowPrivate *priv;
2494 GdkColor *new_color;
2495 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2497 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2498 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2501 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2503 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2505 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2507 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2512 font_size_clicked (GtkToolButton *button,
2513 ModestMsgEditWindow *window)
2515 ModestMsgEditWindowPrivate *priv;
2516 GtkWidget *selector, *dialog;
2518 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2520 selector = hildon_touch_selector_new ();
2521 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2522 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2524 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2525 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2527 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2531 WPTextBufferFormat format;
2533 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2535 memset (&format, 0, sizeof (format));
2536 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2538 format.cs.font_size = TRUE;
2539 format.cs.text_position = TRUE;
2540 format.cs.font = TRUE;
2541 format.font_size = new_index;
2542 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2544 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2545 GINT_TO_POINTER (new_index)))
2546 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2548 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2549 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2550 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2551 size_text, "</span>", NULL);
2553 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2557 gtk_widget_destroy (dialog);
2559 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2564 font_face_clicked (GtkToolButton *button,
2565 ModestMsgEditWindow *window)
2567 ModestMsgEditWindowPrivate *priv;
2568 GtkWidget *selector, *dialog;
2569 GtkCellRenderer *renderer;
2571 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2573 selector = hildon_touch_selector_new ();
2574 renderer = gtk_cell_renderer_text_new ();
2575 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2576 renderer, "family", 0, "text", 0, NULL);
2577 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2579 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2580 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2582 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2583 gint new_font_index;
2587 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2588 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2589 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2593 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2595 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2596 GINT_TO_POINTER(new_font_index)))
2597 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2599 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2600 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2602 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2606 gtk_tree_path_free (path);
2609 gtk_widget_destroy (dialog);
2611 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2616 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2619 ModestMsgEditWindowPrivate *priv = NULL;
2620 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2622 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2623 if (!priv->update_caption_visibility)
2626 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2628 gtk_widget_show (priv->cc_caption);
2630 gtk_widget_hide (priv->cc_caption);
2632 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2636 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2639 ModestMsgEditWindowPrivate *priv = NULL;
2640 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2642 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2643 if (!priv->update_caption_visibility)
2646 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2648 gtk_widget_show (priv->bcc_caption);
2650 gtk_widget_hide (priv->bcc_caption);
2652 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2656 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2657 ModestRecptEditor *editor)
2659 ModestMsgEditWindowPrivate *priv;
2661 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2662 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2664 /* we check for low-mem; in that case, show a warning, and don't allow
2665 * for the addressbook
2667 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2670 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2672 if (editor == NULL) {
2673 GtkWidget *view_focus;
2674 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2676 /* This code should be kept in sync with ModestRecptEditor. The
2677 textview inside the recpt editor is the one that really gets the
2678 focus. As it's inside a scrolled window, and this one inside the
2679 hbox recpt editor inherits from, we'll need to go up in the
2680 hierarchy to know if the text view is part of the recpt editor
2681 or if it's a different text entry */
2683 if (gtk_widget_get_parent (view_focus)) {
2684 GtkWidget *first_parent;
2686 first_parent = gtk_widget_get_parent (view_focus);
2687 if (gtk_widget_get_parent (first_parent) &&
2688 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2689 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2694 editor = MODEST_RECPT_EDITOR (priv->to_field);
2698 modest_address_book_select_addresses (editor);
2703 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2705 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2707 modest_msg_edit_window_open_addressbook (window, NULL);
2711 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2712 gboolean show_toolbar)
2714 ModestWindowPrivate *parent_priv;
2716 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2717 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2719 /* We can not just use the code of
2720 modest_msg_edit_window_setup_toolbar because it has a
2721 mixture of both initialization and creation code. */
2723 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2725 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2729 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2730 TnyHeaderFlags priority_flags)
2732 ModestMsgEditWindowPrivate *priv;
2733 ModestWindowPrivate *parent_priv;
2735 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2737 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2738 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2740 if (priv->priority_flags != priority_flags) {
2741 GtkAction *priority_action = NULL;
2743 priv->priority_flags = priority_flags;
2745 switch (priority_flags) {
2746 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2747 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2748 MODEST_HEADER_ICON_HIGH,
2749 HILDON_ICON_SIZE_SMALL);
2750 gtk_widget_show (priv->priority_icon);
2751 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2752 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2754 case TNY_HEADER_FLAG_LOW_PRIORITY:
2755 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2756 MODEST_HEADER_ICON_LOW,
2757 HILDON_ICON_SIZE_SMALL);
2758 gtk_widget_show (priv->priority_icon);
2759 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2760 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2763 gtk_widget_hide (priv->priority_icon);
2764 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2765 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2768 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2769 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2771 gtk_widget_queue_resize (priv->subject_box);
2775 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2778 ModestMsgEditWindowPrivate *priv;
2779 ModestWindowPrivate *parent_priv;
2780 gint current_format;
2782 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2784 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2785 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2787 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2788 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2790 if (current_format != file_format) {
2791 switch (file_format) {
2792 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2793 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2794 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2796 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2800 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2801 response = gtk_dialog_run (GTK_DIALOG (dialog));
2802 gtk_widget_destroy (dialog);
2803 if (response == GTK_RESPONSE_OK) {
2804 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2806 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2807 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2812 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2813 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2814 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2819 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2822 ModestMsgEditWindowPrivate *priv;
2823 WPTextBufferFormat oldfmt, fmt;
2824 gint old_position = 0;
2828 GdkColor *color = NULL;
2829 gboolean bold, bold_set, italic, italic_set;
2830 gboolean underline, underline_set;
2831 gboolean strikethrough, strikethrough_set;
2832 gboolean position_set;
2833 gboolean font_size_set, font_set, color_set;
2836 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2837 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2839 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2840 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2841 GTK_WINDOW(dialog), GTK_WINDOW (window));
2843 /* First we get the currently selected font information */
2844 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2846 switch (oldfmt.text_position) {
2847 case TEXT_POSITION_NORMAL:
2850 case TEXT_POSITION_SUPERSCRIPT:
2858 g_object_set (G_OBJECT (dialog),
2859 "bold", oldfmt.bold != FALSE,
2860 "bold-set", !oldfmt.cs.bold,
2861 "underline", oldfmt.underline != FALSE,
2862 "underline-set", !oldfmt.cs.underline,
2863 "italic", oldfmt.italic != FALSE,
2864 "italic-set", !oldfmt.cs.italic,
2865 "strikethrough", oldfmt.strikethrough != FALSE,
2866 "strikethrough-set", !oldfmt.cs.strikethrough,
2867 "color", &oldfmt.color,
2868 "color-set", !oldfmt.cs.color,
2869 "size", wp_font_size[oldfmt.font_size],
2870 "size-set", !oldfmt.cs.font_size,
2871 "position", old_position,
2872 "position-set", !oldfmt.cs.text_position,
2873 "family", wp_get_font_name (oldfmt.font),
2874 "family-set", !oldfmt.cs.font,
2877 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2878 GTK_WINDOW (dialog), GTK_WINDOW (window));
2879 gtk_widget_show_all (dialog);
2880 priv->font_dialog = dialog;
2881 response = gtk_dialog_run (GTK_DIALOG (dialog));
2882 priv->font_dialog = NULL;
2883 if (response == GTK_RESPONSE_OK) {
2885 g_object_get( dialog,
2887 "bold-set", &bold_set,
2888 "underline", &underline,
2889 "underline-set", &underline_set,
2891 "italic-set", &italic_set,
2892 "strikethrough", &strikethrough,
2893 "strikethrough-set", &strikethrough_set,
2895 "color-set", &color_set,
2897 "size-set", &font_size_set,
2898 "family", &font_name,
2899 "family-set", &font_set,
2900 "position", &position,
2901 "position-set", &position_set,
2906 if (response == GTK_RESPONSE_OK) {
2907 memset(&fmt, 0, sizeof(fmt));
2913 fmt.italic = italic;
2914 fmt.cs.italic = TRUE;
2916 if (underline_set) {
2917 fmt.underline = underline;
2918 fmt.cs.underline = TRUE;
2920 if (strikethrough_set) {
2921 fmt.strikethrough = strikethrough;
2922 fmt.cs.strikethrough = TRUE;
2927 ? TEXT_POSITION_NORMAL
2928 : ( ( position == 1 )
2929 ? TEXT_POSITION_SUPERSCRIPT
2930 : TEXT_POSITION_SUBSCRIPT );
2931 fmt.cs.text_position = TRUE;
2932 fmt.font_size = oldfmt.font_size;
2936 fmt.cs.color = TRUE;
2939 fmt.font = wp_get_font_index(font_name,
2944 if (font_size_set) {
2945 fmt.cs.font_size = TRUE;
2946 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2948 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2949 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2951 gtk_widget_destroy (dialog);
2953 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2957 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2959 ModestMsgEditWindowPrivate *priv;
2961 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2962 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2964 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2966 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2967 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2971 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2973 ModestMsgEditWindowPrivate *priv;
2975 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2976 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2978 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2980 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2981 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2986 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2988 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2990 priv->can_undo = can_undo;
2994 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2996 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2998 priv->can_redo = can_redo;
3002 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3004 ModestMsgEditWindowPrivate *priv;
3005 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3006 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3008 return priv->can_undo;
3012 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3014 ModestMsgEditWindowPrivate *priv;
3015 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3016 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3018 return priv->can_redo;
3023 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3026 GtkTextIter match_start, match_end;
3028 if (image_id == NULL)
3031 gtk_text_buffer_get_start_iter (buffer, &iter);
3033 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3034 GSList *tags = gtk_text_iter_get_tags (&match_start);
3036 for (node = tags; node != NULL; node = g_slist_next (node)) {
3037 GtkTextTag *tag = (GtkTextTag *) node->data;
3038 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3039 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3040 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3042 offset = gtk_text_iter_get_offset (&match_start);
3043 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3044 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3048 gtk_text_iter_forward_char (&iter);
3053 message_is_empty (ModestMsgEditWindow *window)
3055 ModestMsgEditWindowPrivate *priv = NULL;
3057 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3058 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3060 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3061 * so we can ignore markup.
3063 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3066 count = gtk_text_buffer_get_char_count (buf);
3072 msg_body_focus (GtkWidget *focus,
3073 GdkEventFocus *event,
3077 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3078 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3079 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3084 recpt_field_changed (GtkTextBuffer *buffer,
3085 ModestMsgEditWindow *editor)
3087 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3088 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3092 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3094 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3095 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3099 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3102 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3103 GtkTextBuffer *buffer;
3105 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3106 gtk_text_buffer_set_modified (buffer, modified);
3107 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3108 gtk_text_buffer_set_modified (buffer, modified);
3109 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3110 gtk_text_buffer_set_modified (buffer, modified);
3111 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3115 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3117 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3118 const char *account_name;
3119 GtkTextBuffer *buffer;
3121 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3122 if (gtk_text_buffer_get_modified (buffer))
3124 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3125 if (gtk_text_buffer_get_modified (buffer))
3127 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3128 if (gtk_text_buffer_get_modified (buffer))
3130 if (gtk_text_buffer_get_modified (priv->text_buffer))
3132 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3133 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3144 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3146 ModestMsgEditWindowPrivate *priv = NULL;
3148 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3149 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3151 /* check if there's no recipient added */
3152 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3153 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3154 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3155 /* no recipient contents, then select contacts */
3156 modest_msg_edit_window_open_addressbook (window, NULL);
3160 g_object_ref (window);
3161 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3162 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3163 g_object_unref (window);
3166 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3167 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3168 g_object_unref (window);
3171 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3172 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3173 g_object_unref (window);
3177 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3178 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3179 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3180 g_object_unref (window);
3187 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3188 ModestMsgEditWindow *window)
3190 modest_msg_edit_window_offer_attach_file (window);
3194 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3196 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3198 return priv->clipboard_text;
3202 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3204 ModestMsgEditWindow *window)
3206 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3207 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3209 if (!GTK_WIDGET_VISIBLE (window))
3212 g_object_ref (window);
3213 text = gtk_clipboard_wait_for_text (selection_clipboard);
3215 if (priv->clipboard_text != NULL) {
3216 g_free (priv->clipboard_text);
3218 priv->clipboard_text = text;
3220 if (GTK_WIDGET_VISIBLE (window)) {
3221 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3223 g_object_unref (window);
3226 static gboolean clipboard_owner_change_idle (gpointer userdata)
3228 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3229 ModestMsgEditWindowPrivate *priv;
3231 gdk_threads_enter ();
3232 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3233 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3235 priv->clipboard_owner_idle = 0;
3236 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3237 gdk_threads_leave ();
3243 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3245 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3246 if (priv->clipboard_owner_idle == 0) {
3247 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3252 subject_field_move_cursor (GtkEntry *entry,
3253 GtkMovementStep step,
3258 if (!GTK_WIDGET_VISIBLE (window))
3261 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3265 update_window_title (ModestMsgEditWindow *window)
3267 ModestMsgEditWindowPrivate *priv = NULL;
3268 const gchar *subject;
3270 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3271 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3272 if (subject == NULL || subject[0] == '\0')
3273 subject = _("mail_va_new_email");
3275 gtk_window_set_title (GTK_WINDOW (window), subject);
3280 subject_field_changed (GtkEditable *editable,
3281 ModestMsgEditWindow *window)
3283 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3284 update_window_title (window);
3285 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3286 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3287 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3291 subject_field_insert_text (GtkEditable *editable,
3293 gint new_text_length,
3295 ModestMsgEditWindow *window)
3297 GString *result = g_string_new ("");
3299 gint result_len = 0;
3300 const gchar *entry_text = NULL;
3303 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3304 old_length = g_utf8_strlen (entry_text, -1);
3306 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3307 gunichar c = g_utf8_get_char_validated (current, 8);
3308 /* Invalid unichar, stop */
3314 result = g_string_append_unichar (result, c);
3318 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3319 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3322 /* Prevent endless recursion */
3323 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3324 g_signal_emit_by_name (editable, "insert-text",
3325 (gpointer) result->str, (gpointer) result->len,
3326 (gpointer) position, (gpointer) window);
3327 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3331 if (result_len + old_length > 1000) {
3332 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3333 _CS("ckdg_ib_maximum_characters_reached"));
3335 g_string_free (result, TRUE);
3339 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3342 ModestMsgEditWindowPrivate *priv = NULL;
3344 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3345 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3347 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3350 gtk_widget_show_all (priv->find_toolbar);
3351 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3353 gtk_widget_hide_all (priv->find_toolbar);
3354 gtk_widget_grab_focus (priv->msg_body);
3359 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3361 GtkTextIter *match_start,
3362 GtkTextIter *match_end)
3364 GtkTextIter end_iter;
3365 gchar *str_casefold;
3368 gchar *range_casefold;
3371 gboolean result = FALSE;
3378 gtk_text_iter_forward_to_end (&end_iter);
3380 str_casefold = g_utf8_casefold (str, -1);
3381 str_chars_n = strlen (str);
3383 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3384 range_casefold = g_utf8_casefold (range_text, -1);
3385 range_chars_n = strlen (range_casefold);
3387 if (range_chars_n < str_chars_n) {
3388 g_free (str_casefold);
3389 g_free (range_text);
3390 g_free (range_casefold);
3394 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3395 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3396 if (!g_utf8_collate (range_subtext, str_casefold)) {
3397 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3399 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3400 match_start, match_end, NULL);
3401 g_free (found_text);
3403 g_free (range_subtext);
3407 g_free (str_casefold);
3408 g_free (range_text);
3409 g_free (range_casefold);
3416 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3417 ModestMsgEditWindow *window)
3419 gchar *current_search = NULL;
3420 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3422 GtkTextIter selection_start, selection_end;
3423 GtkTextIter match_start, match_end;
3424 gboolean continue_search = FALSE;
3426 if (message_is_empty (window)) {
3427 g_free (priv->last_search);
3428 priv->last_search = NULL;
3429 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3433 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3434 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3435 g_free (current_search);
3436 g_free (priv->last_search);
3437 priv->last_search = NULL;
3438 /* Information banner about empty search */
3439 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3443 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3444 continue_search = TRUE;
3446 g_free (priv->last_search);
3447 priv->last_search = g_strdup (current_search);
3450 if (continue_search) {
3451 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3452 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3453 &match_start, &match_end);
3455 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3457 GtkTextIter buffer_start;
3458 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3459 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3460 &match_start, &match_end);
3462 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3465 /* Mark as selected the string found in search */
3467 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3468 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3469 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3471 g_free (priv->last_search);
3472 priv->last_search = NULL;
3474 g_free (current_search);
3478 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3480 ModestMsgEditWindowPrivate *priv;
3482 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3487 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3490 ModestMsgEditWindowPrivate *priv;
3492 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3497 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3498 ModestMsgEditWindow *window)
3500 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3504 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3507 ModestMsgEditWindowPrivate *priv;
3508 TnyHeader *header = NULL;
3510 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3511 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3513 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3514 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3516 if (priv->draft_msg != NULL) {
3517 g_object_unref (priv->draft_msg);
3520 if (draft != NULL) {
3521 g_object_ref (draft);
3522 header = tny_msg_get_header (draft);
3523 if (priv->msg_uid) {
3524 g_free (priv->msg_uid);
3525 priv->msg_uid = NULL;
3527 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3528 if (GTK_WIDGET_REALIZED (window)) {
3529 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3530 gtk_widget_destroy (GTK_WIDGET (window));
3536 priv->draft_msg = draft;
3540 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3541 GtkTextIter *start, GtkTextIter *end,
3544 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3545 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3548 if (tag == NULL) return;
3549 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3550 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3551 replace_with_images (window, priv->images);
3556 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3559 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3561 g_return_if_fail (TNY_IS_MIME_PART (part));
3562 tny_list_prepend (priv->attachments, (GObject *) part);
3563 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3564 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3565 gtk_widget_show_all (priv->attachments_caption);
3566 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3570 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3572 ModestMsgEditWindowPrivate *priv;
3574 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3575 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3577 return priv->msg_uid;
3581 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3582 ModestMsgEditWindowWidgetType widget_type)
3584 ModestMsgEditWindowPrivate *priv;
3586 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3587 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3589 switch (widget_type) {
3590 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3591 return priv->msg_body;
3593 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3594 return priv->to_field;
3596 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3597 return priv->cc_field;
3599 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3600 return priv->bcc_field;
3602 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3603 return priv->subject_field;
3605 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3606 return priv->attachments_view;
3614 remove_tags (WPTextBuffer *buffer)
3616 GtkTextIter start, end;
3618 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3619 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3621 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3625 on_account_removed (TnyAccountStore *account_store,
3626 TnyAccount *account,
3629 /* Do nothing if it's a store account, because we use the
3630 transport to send the messages */
3631 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3632 const gchar *parent_acc = NULL;
3633 const gchar *our_acc = NULL;
3635 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3636 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3637 /* Close this window if I'm showing a message of the removed account */
3638 if (strcmp (parent_acc, our_acc) == 0)
3639 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3644 from_field_changed (HildonPickerButton *button,
3645 ModestMsgEditWindow *self)
3647 ModestMsgEditWindowPrivate *priv;
3648 gboolean has_old_signature, has_new_signature;
3650 GtkTextIter match_start, match_end;
3651 ModestAccountMgr *mgr;
3653 gchar *full_signature;
3655 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3657 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3658 mgr = modest_runtime_get_account_mgr ();
3659 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3660 if (has_old_signature) {
3661 full_signature = g_strconcat ("\n--\n", signature, NULL);
3662 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3663 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3665 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3666 &match_start, &match_end, NULL)) {
3669 g_free (full_signature);
3673 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3674 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3675 if (has_new_signature) {
3676 full_signature = g_strconcat ("\n--\n", signature, NULL);
3677 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3678 g_free (full_signature);
3683 typedef struct _MessageSettingsHelper {
3684 ModestMsgEditWindow *window;
3685 GSList *priority_group;
3686 GSList *format_group;
3687 GtkToggleButton *current_priority;
3688 GtkToggleButton *current_format;
3689 } MessageSettingsHelper;
3692 on_priority_toggle (GtkToggleButton *button,
3693 MessageSettingsHelper *helper)
3696 ModestMsgEditWindowPrivate *priv;
3698 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3699 if (gtk_toggle_button_get_active (button)) {
3701 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3702 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3703 if ((node_button != button) &&
3704 gtk_toggle_button_get_active (node_button)) {
3705 gtk_toggle_button_set_active (node_button, FALSE);
3708 helper->current_priority = button;
3710 gboolean found = FALSE;
3711 /* If no one is active, activate it again */
3712 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3713 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3714 if (gtk_toggle_button_get_active (node_button)) {
3720 gtk_toggle_button_set_active (button, TRUE);
3726 on_format_toggle (GtkToggleButton *button,
3727 MessageSettingsHelper *helper)
3730 ModestMsgEditWindowPrivate *priv;
3732 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3733 if (gtk_toggle_button_get_active (button)) {
3735 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3736 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3737 if ((node_button != button) &&
3738 gtk_toggle_button_get_active (node_button)) {
3739 gtk_toggle_button_set_active (node_button, FALSE);
3742 helper->current_format = button;
3744 gboolean found = FALSE;
3745 /* If no one is active, activate it again */
3746 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3747 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3748 if (gtk_toggle_button_get_active (node_button)) {
3754 gtk_toggle_button_set_active (button, TRUE);
3761 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3766 GtkWidget *priority_hbox;
3767 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3768 GtkWidget *captioned;
3769 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3770 GtkWidget *format_hbox;
3771 GtkWidget *html_toggle, *text_toggle;
3772 ModestMsgEditWindowPrivate *priv;
3773 MessageSettingsHelper helper = {0,};
3775 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3776 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3777 helper.window = window;
3778 helper.priority_group = NULL;
3779 helper.format_group = NULL;
3781 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3782 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3784 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3785 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3786 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3787 vbox = gtk_vbox_new (FALSE, 0);
3788 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
3789 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
3790 gtk_container_add (GTK_CONTAINER (align), vbox);
3791 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
3792 gtk_widget_show (align);
3793 gtk_widget_show (vbox);
3795 /* Priority toggles */
3796 priority_hbox = gtk_hbox_new (TRUE, 0);
3797 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3798 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3799 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3800 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3801 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3802 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3803 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3804 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3805 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3806 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3807 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3808 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3809 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3810 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3811 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3812 gtk_widget_show_all (priority_hbox);
3813 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3814 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3815 gtk_widget_show (captioned);
3816 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3818 /* format toggles */
3819 format_hbox = gtk_hbox_new (TRUE, 0);
3820 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3821 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3822 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3823 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3824 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3825 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3826 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3827 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3828 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3829 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3830 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3831 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3832 gtk_widget_show_all (format_hbox);
3833 gtk_widget_show (format_hbox);
3834 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3837 g_object_unref (title_sizegroup);
3838 g_object_unref (value_sizegroup);
3840 /* Set current values */
3841 switch (priv->priority_flags) {
3842 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3843 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3844 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3846 case TNY_HEADER_FLAG_LOW_PRIORITY:
3847 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3848 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3851 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3852 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3856 switch (modest_msg_edit_window_get_format (window)) {
3857 case MODEST_MSG_EDIT_FORMAT_TEXT:
3858 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3859 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3861 case MODEST_MSG_EDIT_FORMAT_HTML:
3863 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3864 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3868 /* Signal connects */
3869 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3870 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3871 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3872 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3873 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3875 /* Save settings if the user clicked on done */
3876 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3877 TnyHeaderFlags flags;
3878 ModestMsgEditFormat old_format, new_format;
3880 /* Set priority flags */
3881 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3882 if (priv->priority_flags != flags)
3883 modest_msg_edit_window_set_priority_flags (window, flags);
3885 /* Set edit format */
3886 old_format = modest_msg_edit_window_get_format (window);
3887 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3888 if (old_format != new_format) {
3889 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3890 modest_msg_edit_window_set_file_format (window, file_format);
3894 gtk_widget_destroy (dialog);
3895 g_slist_free (helper.priority_group);
3899 on_message_settings (GtkAction *action,
3900 ModestMsgEditWindow *window)
3902 modest_msg_edit_window_show_msg_settings_dialog (window);
3906 on_cc_button_toggled (HildonCheckButton *button,
3907 ModestMsgEditWindow *window)
3909 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3911 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3912 hildon_check_button_get_active (button));
3916 on_bcc_button_toggled (HildonCheckButton *button,
3917 ModestMsgEditWindow *window)
3919 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3921 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3922 hildon_check_button_get_active (button));
3926 setup_menu (ModestMsgEditWindow *self)
3928 ModestMsgEditWindowPrivate *priv = NULL;
3930 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3932 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3934 /* Settings menu buttons */
3935 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3936 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3938 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3939 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3940 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3942 priv->cc_button = hildon_check_button_new (0);
3943 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3944 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3946 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3948 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3949 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3950 priv->bcc_button = hildon_check_button_new (0);
3951 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3952 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3954 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3956 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3957 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3959 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3960 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3961 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3962 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3963 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3964 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3965 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3966 APP_MENU_CALLBACK (on_message_settings),
3968 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3969 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),