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 /* It could happen that the window was already closed */
489 if (!GTK_WIDGET_VISIBLE (win))
492 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
494 correct_scroll_without_drag_check (win, TRUE);
496 priv->scroll_drag_timeout_id = 0;
502 correct_scroll_without_drag_check_idle (gpointer userdata)
504 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
505 ModestMsgEditWindowPrivate *priv;
507 GdkRectangle rectangle;
508 gint offset_min, offset_max;
512 /* It could happen that the window was already closed */
513 if (!GTK_WIDGET_VISIBLE (w))
516 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
518 insert = gtk_text_buffer_get_insert (priv->text_buffer);
519 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
521 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
522 offset_min = priv->msg_body->allocation.y + rectangle.y;
523 offset_max = offset_min + rectangle.height;
525 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
526 offset_min = MAX (offset_min - 48, 0);
527 offset_max = MIN (offset_max + 48, vadj->upper);
529 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
531 priv->correct_scroll_idle = 0;
536 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
538 ModestMsgEditWindowPrivate *priv;
540 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
542 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
545 if (priv->correct_scroll_idle > 0) {
549 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
550 (GSourceFunc) correct_scroll_without_drag_check_idle,
556 correct_scroll (ModestMsgEditWindow *w)
558 ModestMsgEditWindowPrivate *priv;
560 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
561 if (gtk_grab_get_current () == priv->msg_body) {
562 if (priv->scroll_drag_timeout_id == 0) {
563 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
565 (GSourceFunc) scroll_drag_timeout,
572 correct_scroll_without_drag_check (w, TRUE);
576 text_buffer_end_user_action (GtkTextBuffer *buffer,
577 ModestMsgEditWindow *userdata)
580 correct_scroll (userdata);
584 text_buffer_mark_set (GtkTextBuffer *buffer,
587 ModestMsgEditWindow *userdata)
589 gtk_text_buffer_begin_user_action (buffer);
590 gtk_text_buffer_end_user_action (buffer);
594 cut_clipboard_check (GtkTextView *text_view,
597 GtkTextBuffer *buffer;
599 buffer = gtk_text_view_get_buffer (text_view);
600 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
601 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
606 copy_clipboard_check (GtkTextView *text_view,
609 GtkTextBuffer *buffer;
611 buffer = gtk_text_view_get_buffer (text_view);
612 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
613 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
618 attachment_deleted (ModestAttachmentsView *attachments_view,
621 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
626 connect_signals (ModestMsgEditWindow *obj)
628 ModestMsgEditWindowPrivate *priv;
630 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
632 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
633 G_CALLBACK (text_buffer_refresh_attributes), obj);
634 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
635 G_CALLBACK (text_buffer_can_undo), obj);
636 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
637 G_CALLBACK (text_buffer_can_redo), obj);
638 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
639 G_CALLBACK (body_changed), obj);
640 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
641 G_CALLBACK (body_changed), obj);
642 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
643 G_CALLBACK (text_buffer_end_user_action), obj);
644 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
645 G_CALLBACK (text_buffer_mark_set), obj);
646 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
647 G_CALLBACK (text_buffer_apply_tag), obj);
648 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
649 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
650 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
651 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
652 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
653 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
655 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
656 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
657 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
658 G_CALLBACK (from_field_changed), obj);
660 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
661 G_CALLBACK (msg_body_focus), obj);
662 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
663 G_CALLBACK (msg_body_focus), obj);
664 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
665 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
666 "changed", G_CALLBACK (recpt_field_changed), obj);
667 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
668 "changed", G_CALLBACK (recpt_field_changed), obj);
669 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
670 "changed", G_CALLBACK (recpt_field_changed), obj);
671 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
672 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
673 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
675 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
676 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
678 priv->clipboard_change_handler_id =
679 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
680 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
681 priv->default_clipboard_change_handler_id =
682 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
683 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
685 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
686 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
687 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
691 init_wp_text_view_style ()
693 static gboolean initialized = FALSE;
696 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
702 init_window (ModestMsgEditWindow *obj)
704 GtkWidget *to_caption, *subject_caption;
705 GtkWidget *main_vbox;
706 GtkWidget *add_attachment_align;
707 ModestMsgEditWindowPrivate *priv;
708 GtkActionGroup *action_group;
709 ModestWindowPrivate *parent_priv;
710 GdkPixbuf *window_icon = NULL;
711 GError *error = NULL;
713 GtkSizeGroup *title_size_group;
714 GtkSizeGroup *value_size_group;
715 GtkWidget *attachment_icon;
716 GtkWidget *window_box;
717 GtkWidget *window_align;
718 #if (GTK_MINOR_VERSION >= 10)
719 GdkAtom deserialize_type;
722 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
723 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
725 parent_priv->ui_manager = gtk_ui_manager_new();
726 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
727 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
729 /* Add common actions */
730 gtk_action_group_add_actions (action_group,
731 modest_msg_edit_action_entries,
732 G_N_ELEMENTS (modest_msg_edit_action_entries),
734 gtk_action_group_add_actions (action_group,
735 hildon2_msg_edit_action_entries,
736 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
738 gtk_action_group_add_toggle_actions (action_group,
739 modest_msg_edit_toggle_action_entries,
740 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
742 gtk_action_group_add_radio_actions (action_group,
743 modest_msg_edit_alignment_radio_action_entries,
744 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
746 G_CALLBACK (modest_ui_actions_on_change_justify),
748 gtk_action_group_add_radio_actions (action_group,
749 modest_msg_edit_priority_action_entries,
750 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
752 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
754 gtk_action_group_add_radio_actions (action_group,
755 modest_msg_edit_file_format_action_entries,
756 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
757 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
758 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
760 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
761 g_object_unref (action_group);
763 /* Load the UI definition */
764 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
767 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
768 g_clear_error (&error);
771 /* Add accelerators */
772 gtk_window_add_accel_group (GTK_WINDOW (obj),
773 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
775 parent_priv->menubar = NULL;
777 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
778 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
780 /* Note: This ModestPairList* must exist for as long as the picker
781 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
782 * so it can't know how to manage its memory. */
783 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
784 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
786 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
787 _("mail_va_from"), priv->from_field);
789 priv->to_field = modest_recpt_editor_new ();
790 priv->cc_field = modest_recpt_editor_new ();
791 priv->bcc_field = modest_recpt_editor_new ();
792 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
793 priv->priority_icon = gtk_image_new ();
794 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
795 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
796 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
797 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
798 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
799 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
800 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
801 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
802 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
803 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
804 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
805 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
806 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
807 add_attachment_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
808 gtk_alignment_set_padding (GTK_ALIGNMENT (add_attachment_align), 0, 0, MODEST_MARGIN_DEFAULT, 0);
809 gtk_container_add (GTK_CONTAINER (add_attachment_align), priv->add_attachment_button);
810 gtk_box_pack_start (GTK_BOX (priv->subject_box), add_attachment_align, FALSE, FALSE, 0);
811 priv->attachments_view = modest_attachments_view_new (NULL);
812 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
813 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
815 priv->header_box = gtk_vbox_new (FALSE, 0);
817 to_caption = modest_maemo_utils_create_captioned_with_size_type
818 (title_size_group, value_size_group,
819 _("mail_va_to"), FALSE, priv->to_field,
820 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
821 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
822 (title_size_group, value_size_group,
823 _("mail_va_cc"), FALSE, priv->cc_field,
824 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
825 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
826 (title_size_group, value_size_group,
827 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
828 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
829 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
830 _("mail_va_subject"), FALSE, priv->subject_box);
831 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
832 _("mail_va_attachment"),
834 priv->attachments_view,
835 HILDON_SIZE_AUTO_WIDTH |
836 HILDON_SIZE_AUTO_HEIGHT);
837 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
838 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
839 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
840 g_object_unref (title_size_group);
841 g_object_unref (value_size_group);
843 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
844 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
845 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
846 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
847 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
848 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
849 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
851 init_wp_text_view_style ();
853 priv->msg_body = modest_wp_text_view_new ();
856 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
857 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
858 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
859 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
860 #if (GTK_MINOR_VERSION >= 10)
861 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
862 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
864 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
865 deserialize_type, TRUE);
867 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
869 priv->find_toolbar = hildon_find_toolbar_new (NULL);
870 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
872 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
874 priv->pannable = hildon_pannable_area_new ();
876 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
877 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
878 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
880 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
881 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
882 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
884 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
885 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox),
886 hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable)));
887 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
889 window_box = gtk_vbox_new (FALSE, 0);
890 gtk_container_add (GTK_CONTAINER(obj), window_box);
892 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
894 /* Set window icon */
895 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
897 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
898 g_object_unref (window_icon);
903 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
905 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
907 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
908 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
909 priv->clipboard_change_handler_id))
910 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
911 priv->clipboard_change_handler_id);
912 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
913 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
914 priv->default_clipboard_change_handler_id))
915 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
916 priv->default_clipboard_change_handler_id);
918 if (priv->account_removed_handler_id &&
919 g_signal_handler_is_connected (modest_runtime_get_account_store (),
920 priv->account_removed_handler_id))
921 g_signal_handler_disconnect(modest_runtime_get_account_store (),
922 priv->account_removed_handler_id);
926 modest_msg_edit_window_finalize (GObject *obj)
928 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
930 /* Sanity check: shouldn't be needed, the window mgr should
931 call this function before */
932 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
934 if (priv->font_dialog != NULL) {
935 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
938 if (priv->clipboard_text != NULL) {
939 g_free (priv->clipboard_text);
940 priv->clipboard_text = NULL;
943 if (priv->draft_msg != NULL) {
944 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
945 if (TNY_IS_HEADER (header)) {
946 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
947 modest_window_mgr_unregister_header (mgr, header);
949 g_object_unref (priv->draft_msg);
950 priv->draft_msg = NULL;
952 if (priv->outbox_msg != NULL) {
953 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
954 if (TNY_IS_HEADER (header)) {
955 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
956 modest_window_mgr_unregister_header (mgr, header);
958 g_object_unref (priv->outbox_msg);
959 priv->outbox_msg = NULL;
961 if (priv->correct_scroll_idle > 0) {
962 g_source_remove (priv->correct_scroll_idle);
963 priv->correct_scroll_idle = 0;
965 if (priv->scroll_drag_timeout_id > 0) {
966 g_source_remove (priv->scroll_drag_timeout_id);
967 priv->scroll_drag_timeout_id = 0;
969 if (priv->clipboard_owner_idle > 0) {
970 g_source_remove (priv->clipboard_owner_idle);
971 priv->clipboard_owner_idle = 0;
973 if (priv->original_account_name)
974 g_free (priv->original_account_name);
975 g_free (priv->msg_uid);
976 g_free (priv->last_search);
977 g_object_unref (priv->faces_model);
978 g_object_unref (priv->sizes_model);
979 g_object_unref (priv->attachments);
980 g_object_unref (priv->images);
982 /* This had to stay alive for as long as the picker that used it: */
983 modest_pair_list_free (priv->from_field_protos);
985 G_OBJECT_CLASS(parent_class)->finalize (obj);
989 pixbuf_size_prepared (GdkPixbufLoader *loader,
992 ModestMsgEditWindow *self)
994 gint new_height, new_width;
1001 if (width > IMAGE_MAX_WIDTH) {
1002 new_height = height * IMAGE_MAX_WIDTH / width;
1003 new_width = IMAGE_MAX_WIDTH;
1006 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1010 pixbuf_from_stream (TnyStream *stream,
1011 const gchar *mime_type,
1012 guint64 *stream_size,
1013 ModestMsgEditWindow *self)
1015 GdkPixbufLoader *loader;
1018 GError *error = NULL;
1022 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1024 if (loader == NULL) {
1029 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1031 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1033 tny_stream_reset (TNY_STREAM (stream));
1034 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1035 unsigned char read_buffer[128];
1037 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1039 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1042 /* Allow some UI responsiveness */
1043 while (gtk_events_pending ())
1044 gtk_main_iteration ();
1046 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1048 gdk_pixbuf_loader_close (loader, &error);
1051 g_error_free (error);
1052 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1054 g_object_ref (pixbuf);
1055 g_object_unref (loader);
1060 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1061 GdkPixbuf *new_pixbuf;
1063 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1064 gdk_pixbuf_get_width (pixbuf);
1065 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1066 g_object_unref (pixbuf);
1067 pixbuf = new_pixbuf;
1071 *stream_size = size;
1077 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1079 ModestMsgEditWindowPrivate *priv;
1082 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1084 g_object_ref (self);
1085 for (iter = tny_list_create_iterator (attachments);
1086 !tny_iterator_is_done (iter);
1087 tny_iterator_next (iter)) {
1088 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1089 const gchar *cid = tny_mime_part_get_content_id (part);
1090 const gchar *mime_type = tny_mime_part_get_content_type (part);
1091 if ((cid != NULL)&&(mime_type != NULL)) {
1092 guint64 stream_size;
1093 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1094 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1097 g_object_unref (stream);
1099 if (pixbuf != NULL) {
1100 priv->images_count ++;
1101 priv->images_size += stream_size;
1102 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1103 g_object_unref (pixbuf);
1106 g_object_unref (part);
1108 g_object_unref (iter);
1109 g_object_unref (self);
1113 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1115 TnyMimePart *parent = NULL;
1116 const gchar *content_type = NULL;
1117 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1119 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1121 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1122 parent = g_object_ref (msg);
1123 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1124 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1127 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1128 iter = tny_list_create_iterator (parts);
1129 while (!tny_iterator_is_done (iter)) {
1131 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1132 content_type = tny_mime_part_get_content_type (part);
1133 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1137 g_object_unref (part);
1139 tny_iterator_next (iter);
1141 g_object_unref (iter);
1142 g_object_unref (parts);
1145 if (parent != NULL) {
1146 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1149 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1150 iter = tny_list_create_iterator (parts);
1151 while (!tny_iterator_is_done (iter)) {
1153 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1154 content_type = tny_mime_part_get_content_type (part);
1155 if (content_type && g_str_has_prefix (content_type, "image/")) {
1156 tny_list_prepend (priv->images, (GObject *) part);
1158 g_object_unref (part);
1159 tny_iterator_next (iter);
1161 g_object_unref (iter);
1162 g_object_unref (parts);
1163 g_object_unref (parent);
1168 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1171 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1173 for (iter = tny_list_create_iterator (attachments) ;
1174 !tny_iterator_is_done (iter);
1175 tny_iterator_next (iter)) {
1176 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1177 const gchar *cid = tny_mime_part_get_content_id (part);
1179 char *invalid = NULL;
1180 gint int_cid = strtol (cid, &invalid, 10);
1181 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1182 priv->next_cid = int_cid + 1;
1185 g_object_unref (part);
1187 g_object_unref (iter);
1191 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1194 gchar *to, *cc, *bcc, *subject;
1196 ModestMsgEditWindowPrivate *priv;
1197 ModestWindowPrivate *parent_priv;
1199 TnyHeaderFlags priority_flags;
1200 TnyFolder *msg_folder;
1201 gboolean is_html = FALSE;
1202 gboolean field_view_set;
1204 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1205 g_return_if_fail (TNY_IS_MSG (msg));
1207 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1208 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1210 header = tny_msg_get_header (msg);
1211 to = tny_header_dup_to (header);
1212 cc = tny_header_dup_cc (header);
1213 bcc = tny_header_dup_bcc (header);
1214 subject = tny_header_dup_subject (header);
1215 priority_flags = tny_header_get_priority (header);
1218 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1220 field_view_set = TRUE;
1222 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1223 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1224 gtk_widget_show (priv->cc_caption);
1225 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1226 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1227 gtk_widget_hide (priv->cc_caption);
1228 field_view_set = FALSE;
1230 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1232 field_view_set = TRUE;
1234 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1235 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1236 gtk_widget_show (priv->bcc_caption);
1237 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1238 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1239 gtk_widget_hide (priv->bcc_caption);
1240 field_view_set = FALSE;
1242 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1246 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1247 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1250 update_window_title (self);
1252 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1253 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1255 if ((body == NULL)||(body[0] == '\0')) {
1257 body = modest_text_utils_convert_to_html ("");
1260 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1261 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1264 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1267 /* Add attachments to the view */
1268 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1269 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1270 if (tny_list_get_length (priv->attachments) == 0) {
1271 gtk_widget_hide (priv->attachments_caption);
1273 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1274 gtk_widget_show_all (priv->attachments_caption);
1276 get_related_images (self, msg);
1277 update_next_cid (self, priv->attachments);
1278 update_next_cid (self, priv->images);
1279 replace_with_images (self, priv->images);
1281 if (preserve_is_rich && !is_html) {
1282 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1283 /* Get the default format required from configuration */
1284 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1285 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1288 /* Set the default focus depending on having already a To: field or not */
1289 if ((!to)||(*to == '\0')) {
1290 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1292 gtk_widget_grab_focus (priv->msg_body);
1295 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1297 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1298 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1300 modest_msg_edit_window_set_modified (self, FALSE);
1302 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1303 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1304 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1305 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1307 if (priv->msg_uid) {
1308 g_free (priv->msg_uid);
1309 priv->msg_uid = NULL;
1312 /* we should set a reference to the incoming message if it is a draft */
1313 msg_folder = tny_msg_get_folder (msg);
1315 if (modest_tny_folder_is_local_folder (msg_folder)) {
1316 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1317 if (type == TNY_FOLDER_TYPE_INVALID)
1318 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1320 if (type == TNY_FOLDER_TYPE_DRAFTS)
1321 priv->draft_msg = g_object_ref(msg);
1322 if (type == TNY_FOLDER_TYPE_OUTBOX)
1323 priv->outbox_msg = g_object_ref(msg);
1324 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1326 g_object_unref (msg_folder);
1337 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1339 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1340 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1341 GtkWidget *placeholder;
1342 GtkWidget *tool_item;
1347 GtkWidget *sizes_menu;
1348 GtkWidget *fonts_menu;
1352 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1353 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1354 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1355 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1357 /* Font color placeholder */
1358 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1359 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1362 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1363 priv->font_color_button = hildon_color_button_new ();
1364 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1365 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1366 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1367 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1368 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1369 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1370 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1371 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1373 G_CALLBACK (modest_msg_edit_window_color_button_change),
1376 /* Font size and face placeholder */
1377 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1378 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1380 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1381 priv->size_tool_button_label = gtk_label_new (NULL);
1382 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1383 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1384 size_text, "</span>", NULL);
1385 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1387 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1388 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1389 sizes_menu = gtk_menu_new ();
1390 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1391 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1394 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1395 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1397 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1401 if (wp_font_size[size_index] == 12)
1402 priv->current_size_index = size_index;
1406 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1407 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1408 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1409 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1410 priv->font_size_toolitem = tool_item;
1413 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1414 priv->font_tool_button_label = gtk_label_new (NULL);
1415 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1416 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1418 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1419 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1420 fonts_menu = gtk_menu_new ();
1421 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1422 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1425 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1427 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1428 0, wp_get_font_name (font_index),
1431 if (font_index == DEFAULT_FONT)
1432 priv->current_face_index = font_index;
1434 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1435 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1436 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1437 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1438 priv->font_face_toolitem = tool_item;
1440 /* Set expand and homogeneous for remaining items */
1441 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1442 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1443 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1444 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1445 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1446 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1447 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1448 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1449 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1451 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1452 will not show the tool items added to the placeholders) */
1453 gtk_widget_show_all (parent_priv->toolbar);
1455 /* Set the no show all *after* showing all items. We do not
1456 want the toolbar to be shown with a show all because it
1457 could go agains the gconf setting regarding showing or not
1458 the toolbar of the editor window */
1459 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1465 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1468 ModestWindowPrivate *parent_priv;
1469 ModestMsgEditWindowPrivate *priv;
1470 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1471 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1472 ModestWindowMgr *mgr = NULL;
1474 g_return_val_if_fail (msg, NULL);
1475 g_return_val_if_fail (account_name, NULL);
1477 mgr = modest_runtime_get_window_mgr ();
1479 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1481 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1482 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1484 /* Menubar. Update the state of some toggles */
1485 priv->from_field_protos = get_transports ();
1486 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1487 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1488 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1489 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1491 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1492 hildon_touch_selector_get_current_text
1493 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1494 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1495 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1498 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1500 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1502 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1504 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1506 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1507 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1508 /* Add common dimming rules */
1509 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1510 modest_msg_edit_window_toolbar_dimming_entries,
1511 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1512 MODEST_WINDOW (obj));
1513 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1514 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1515 MODEST_WINDOW (obj));
1516 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1517 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1518 MODEST_WINDOW (obj));
1519 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1520 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1521 MODEST_WINDOW (obj));
1522 /* Insert dimming rules group for this window */
1523 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1524 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1526 /* Setup app menu */
1527 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1529 /* Checks the dimming rules */
1530 g_object_unref (toolbar_rules_group);
1531 g_object_unref (clipboard_rules_group);
1532 gtk_widget_hide (priv->priority_icon);
1533 gtk_widget_queue_resize (priv->subject_box);
1534 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1536 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1538 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1539 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1540 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1541 priv->update_caption_visibility = TRUE;
1543 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1545 /* Track account-removed signal, this window should be closed
1546 in the case we're creating a mail associated to the account
1548 priv->account_removed_handler_id =
1549 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1551 G_CALLBACK(on_account_removed),
1554 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1556 return (ModestWindow*) obj;
1560 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1562 GString **string_buffer = (GString **) user_data;
1564 *string_buffer = g_string_append (*string_buffer, buffer);
1570 * @result: A new string which should be freed with g_free().
1573 get_formatted_data (ModestMsgEditWindow *edit_window)
1575 ModestMsgEditWindowPrivate *priv;
1576 GString *string_buffer = g_string_new ("");
1578 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1580 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1582 modest_text_utils_hyperlinkify (string_buffer);
1584 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1586 return g_string_free (string_buffer, FALSE);
1591 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1594 const gchar *account_name;
1595 ModestMsgEditWindowPrivate *priv;
1596 TnyIterator *att_iter;
1598 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1600 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1602 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1603 g_return_val_if_fail (account_name, NULL);
1606 /* don't free these (except from) */
1607 data = g_slice_new0 (MsgData);
1608 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1610 data->account_name = g_strdup (account_name);
1611 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1612 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1613 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1614 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1615 if (priv->draft_msg) {
1616 data->draft_msg = g_object_ref (priv->draft_msg);
1617 } else if (priv->outbox_msg) {
1618 data->draft_msg = g_object_ref (priv->outbox_msg);
1620 data->draft_msg = NULL;
1623 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1625 gtk_text_buffer_get_bounds (buf, &b, &e);
1626 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1628 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1629 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1631 data->html_body = NULL;
1633 /* deep-copy the data */
1634 att_iter = tny_list_create_iterator (priv->attachments);
1635 data->attachments = NULL;
1636 while (!tny_iterator_is_done (att_iter)) {
1637 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1638 if (!(TNY_IS_MIME_PART(part))) {
1639 g_warning ("strange data in attachment list");
1640 g_object_unref (part);
1641 tny_iterator_next (att_iter);
1644 data->attachments = g_list_append (data->attachments,
1646 tny_iterator_next (att_iter);
1648 g_object_unref (att_iter);
1650 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1651 att_iter = tny_list_create_iterator (priv->images);
1652 data->images = NULL;
1653 while (!tny_iterator_is_done (att_iter)) {
1654 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1656 if (!(TNY_IS_MIME_PART(part))) {
1657 g_warning ("strange data in attachment list");
1658 g_object_unref (part);
1659 tny_iterator_next (att_iter);
1662 cid = tny_mime_part_get_content_id (part);
1664 gchar *image_tag_id;
1665 GtkTextTag *image_tag;
1667 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1668 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1669 g_free (image_tag_id);
1671 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1673 ((gtk_text_iter_has_tag (&iter, image_tag))||
1674 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1675 data->images = g_list_append (data->images,
1676 g_object_ref (part));
1678 g_object_unref (part);
1679 tny_iterator_next (att_iter);
1681 g_object_unref (att_iter);
1683 data->priority_flags = priv->priority_flags;
1690 unref_gobject (GObject *obj, gpointer data)
1692 if (!G_IS_OBJECT(obj))
1694 g_object_unref (obj);
1698 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1701 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1709 g_free (data->from);
1710 g_free (data->subject);
1711 g_free (data->plain_body);
1712 g_free (data->html_body);
1713 g_free (data->account_name);
1715 if (data->draft_msg != NULL) {
1716 g_object_unref (data->draft_msg);
1717 data->draft_msg = NULL;
1720 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1721 g_list_free (data->attachments);
1722 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1723 g_list_free (data->images);
1725 g_slice_free (MsgData, data);
1729 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1731 guint64 *parts_size)
1733 ModestMsgEditWindowPrivate *priv;
1735 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1737 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1739 /* TODO: add images */
1740 *parts_size += priv->images_size;
1741 *parts_count += priv->images_count;
1746 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1749 ModestMsgEditWindowPrivate *priv = NULL;
1750 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1752 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1754 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1756 return MODEST_MSG_EDIT_FORMAT_HTML;
1758 return MODEST_MSG_EDIT_FORMAT_TEXT;
1762 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1763 ModestMsgEditFormat format)
1765 ModestMsgEditWindowPrivate *priv;
1767 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1768 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1771 case MODEST_MSG_EDIT_FORMAT_HTML:
1772 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1774 case MODEST_MSG_EDIT_FORMAT_TEXT:
1775 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1778 g_return_if_reached ();
1782 ModestMsgEditFormatState *
1783 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1785 ModestMsgEditFormatState *format_state = NULL;
1786 ModestMsgEditWindowPrivate *priv;
1787 WPTextBufferFormat *buffer_format;
1789 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1791 buffer_format = g_new0 (WPTextBufferFormat, 1);
1792 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1794 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1796 format_state = g_new0 (ModestMsgEditFormatState, 1);
1797 format_state->bold = buffer_format->bold&0x1;
1798 format_state->italics = buffer_format->italic&0x1;
1799 format_state->bullet = buffer_format->bullet&0x1;
1800 format_state->color = buffer_format->color;
1801 format_state->font_size = buffer_format->font_size;
1802 format_state->font_family = wp_get_font_name (buffer_format->font);
1803 format_state->justification = buffer_format->justification;
1804 g_free (buffer_format);
1806 return format_state;
1811 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1812 const ModestMsgEditFormatState *format_state)
1814 ModestMsgEditWindowPrivate *priv;
1815 WPTextBufferFormat *buffer_format;
1816 WPTextBufferFormat *current_format;
1818 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1819 g_return_if_fail (format_state != NULL);
1821 buffer_format = g_new0 (WPTextBufferFormat, 1);
1822 current_format = g_new0 (WPTextBufferFormat, 1);
1824 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1825 gtk_widget_grab_focus (priv->msg_body);
1826 buffer_format->bold = (format_state->bold != FALSE);
1827 buffer_format->italic = (format_state->italics != FALSE);
1828 buffer_format->color = format_state->color;
1829 buffer_format->font_size = format_state->font_size;
1830 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1831 buffer_format->justification = format_state->justification;
1832 buffer_format->bullet = format_state->bullet;
1834 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1836 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1837 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1838 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1839 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1840 buffer_format->cs.font = (buffer_format->font != current_format->font);
1841 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1842 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1844 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1845 if (buffer_format->cs.bold) {
1846 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1847 GINT_TO_POINTER (buffer_format->bold&0x1));
1849 if (buffer_format->cs.italic) {
1850 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1851 GINT_TO_POINTER (buffer_format->italic&0x1));
1853 if (buffer_format->cs.color) {
1854 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1855 GINT_TO_POINTER (&(buffer_format->color)));
1857 if (buffer_format->cs.font_size) {
1858 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1859 GINT_TO_POINTER (buffer_format->font_size));
1861 if (buffer_format->cs.justification) {
1862 switch (buffer_format->justification) {
1863 case GTK_JUSTIFY_LEFT:
1864 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1865 GINT_TO_POINTER(TRUE));
1867 case GTK_JUSTIFY_CENTER:
1868 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1869 GINT_TO_POINTER(TRUE));
1871 case GTK_JUSTIFY_RIGHT:
1872 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1873 GINT_TO_POINTER(TRUE));
1880 if (buffer_format->cs.font) {
1881 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1882 GINT_TO_POINTER (buffer_format->font));
1884 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1885 if (buffer_format->cs.bullet) {
1886 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1887 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1889 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1891 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1893 g_free (buffer_format);
1894 g_free (current_format);
1896 /* Check dimming rules */
1897 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1898 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1902 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1904 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1906 ModestWindowPrivate *parent_priv;
1907 ModestMsgEditWindowPrivate *priv;
1909 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1910 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1912 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1913 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1914 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1915 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1917 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1918 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1919 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1922 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1924 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1925 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1927 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1928 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1930 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1931 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1934 switch (buffer_format->justification)
1936 case GTK_JUSTIFY_LEFT:
1937 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1939 case GTK_JUSTIFY_CENTER:
1940 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1942 case GTK_JUSTIFY_RIGHT:
1943 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1950 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1952 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1953 G_CALLBACK (modest_msg_edit_window_color_button_change),
1955 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1956 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1957 G_CALLBACK (modest_msg_edit_window_color_button_change),
1960 if (priv->current_size_index != buffer_format->font_size) {
1964 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
1965 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
1969 priv->current_size_index = buffer_format->font_size;
1971 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
1972 markup = g_strconcat ("<span font_family='Sans'>",
1973 size_text, "</span>", NULL);
1975 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1979 gtk_tree_path_free (path);
1982 if (priv->current_face_index != buffer_format->font) {
1986 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
1987 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
1991 priv->current_face_index = buffer_format->font;
1992 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
1993 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
1994 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2001 g_free (buffer_format);
2005 #ifdef MODEST_HILDON_VERSION_0
2007 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2010 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2011 ModestMsgEditWindowPrivate *priv;
2012 GtkWidget *dialog = NULL;
2014 GdkColor *new_color = NULL;
2016 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2017 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2019 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2020 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2021 g_free (buffer_format);
2023 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2024 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2025 if (new_color != NULL) {
2026 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2027 (gpointer) new_color);
2030 gtk_widget_destroy (dialog);
2035 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2038 ModestMsgEditWindowPrivate *priv;
2039 GtkWidget *dialog = NULL;
2041 GdkColor *old_color = NULL;
2042 const GdkColor *new_color = NULL;
2044 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2045 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2047 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2048 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2050 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2051 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2052 if (new_color != NULL)
2053 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2055 gtk_widget_destroy (dialog);
2061 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2064 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2065 ModestMsgEditWindowPrivate *priv;
2066 GtkWidget *dialog = NULL;
2068 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2069 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2071 dialog = hildon_color_chooser_new ();
2072 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2073 g_free (buffer_format);
2075 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2077 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2078 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2081 gtk_widget_destroy (dialog);
2086 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2089 ModestMsgEditWindowPrivate *priv;
2090 GtkWidget *dialog = NULL;
2091 GdkColor *old_color = NULL;
2093 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2094 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2096 dialog = hildon_color_chooser_new ();
2097 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2099 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2101 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2102 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2104 gtk_widget_destroy (dialog);
2107 #endif /*!MODEST_HILDON_VERSION_0*/
2112 create_stream_for_uri (const gchar* uri)
2117 TnyStream *result = NULL;
2119 GnomeVFSHandle *handle = NULL;
2120 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2121 if (test == GNOME_VFS_OK) {
2122 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2123 /* Streams over OBEX (Bluetooth) are not seekable but
2124 * we expect them to be (we might need to read them
2125 * several times). So if this is a Bluetooth URI just
2126 * read the whole file into memory (this is not a fast
2127 * protocol so we can assume that these files are not
2128 * going to be very big) */
2129 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2130 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2131 TnyStream *memstream = tny_camel_mem_stream_new ();
2132 tny_stream_write_to_stream (vfssstream, memstream);
2133 g_object_unref (vfssstream);
2136 result = vfssstream;
2144 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2147 ModestMsgEditWindowPrivate *priv;
2148 GtkWidget *dialog = NULL;
2150 GSList *uris = NULL;
2151 GSList *uri_node = NULL;
2153 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2155 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2156 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2157 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2159 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2161 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2162 GTK_WINDOW (dialog), GTK_WINDOW (window));
2164 response = gtk_dialog_run (GTK_DIALOG (dialog));
2166 case GTK_RESPONSE_OK:
2167 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2172 gtk_widget_destroy (dialog);
2174 g_object_ref (window);
2175 /* The operation could take some time so allow the dialog to be closed */
2176 while (gtk_events_pending ())
2177 gtk_main_iteration ();
2179 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2181 GnomeVFSHandle *handle = NULL;
2182 GnomeVFSResult result;
2183 GtkTextIter position;
2184 GtkTextMark *insert_mark;
2186 uri = (const gchar *) uri_node->data;
2187 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2188 if (result == GNOME_VFS_OK) {
2190 GnomeVFSFileInfo *info;
2191 gchar *filename, *basename, *escaped_filename;
2192 TnyMimePart *mime_part;
2194 const gchar *mime_type = NULL;
2195 GnomeVFSURI *vfs_uri;
2196 guint64 stream_size;
2198 gnome_vfs_close (handle);
2199 vfs_uri = gnome_vfs_uri_new (uri);
2201 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2202 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2203 g_free (escaped_filename);
2204 gnome_vfs_uri_unref (vfs_uri);
2205 info = gnome_vfs_file_info_new ();
2207 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2208 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2210 mime_type = gnome_vfs_file_info_get_mime_type (info);
2212 mime_part = tny_platform_factory_new_mime_part
2213 (modest_runtime_get_platform_factory ());
2215 TnyStream *stream = create_stream_for_uri (uri);
2217 if (stream == NULL) {
2219 modest_platform_information_banner (NULL, NULL,
2220 _FM("sfil_ib_opening_not_allowed"));
2222 g_object_unref (mime_part);
2223 gnome_vfs_file_info_unref (info);
2227 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2229 content_id = g_strdup_printf ("%d", priv->next_cid);
2230 tny_mime_part_set_content_id (mime_part, content_id);
2231 g_free (content_id);
2234 basename = g_path_get_basename (filename);
2235 tny_mime_part_set_filename (mime_part, basename);
2238 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2240 if (pixbuf != NULL) {
2241 priv->images_size += stream_size;
2242 priv->images_count ++;
2243 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2244 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2245 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2246 tny_mime_part_get_content_id (mime_part), pixbuf);
2247 g_object_unref (pixbuf);
2249 tny_list_prepend (priv->images, (GObject *) mime_part);
2250 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2252 modest_platform_information_banner (NULL, NULL,
2253 _("mail_ib_file_operation_failed"));
2257 g_object_unref (mime_part);
2258 gnome_vfs_file_info_unref (info);
2262 g_object_unref (window);
2266 on_attach_file_response (GtkDialog *dialog,
2270 GSList *uris = NULL;
2272 GnomeVFSFileSize total_size, allowed_size;
2273 ModestMsgEditWindow *window;
2274 ModestMsgEditWindowPrivate *priv;
2279 case GTK_RESPONSE_OK:
2280 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2286 window = MODEST_MSG_EDIT_WINDOW (user_data);
2287 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2289 /* allowed size is the maximum size - what's already there */
2290 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2291 &att_num, &att_size);
2292 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2295 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2297 const gchar *uri = (const gchar *) uri_node->data;
2300 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2302 if (total_size > allowed_size) {
2303 g_warning ("%s: total size: %u",
2304 __FUNCTION__, (unsigned int)total_size);
2307 allowed_size -= total_size;
2309 g_slist_foreach (uris, (GFunc) g_free, NULL);
2310 g_slist_free (uris);
2312 gtk_widget_destroy (GTK_WIDGET (dialog));
2316 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2318 GtkWidget *dialog = NULL;
2319 ModestMsgEditWindowPrivate *priv;
2321 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2323 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2325 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2328 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2329 GTK_FILE_CHOOSER_ACTION_OPEN);
2330 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2331 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2332 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2333 GTK_WINDOW (dialog), GTK_WINDOW (window));
2335 /* Connect to response & show */
2336 g_signal_connect (dialog, "response",
2337 G_CALLBACK (on_attach_file_response), window);
2338 gtk_widget_show (dialog);
2343 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2345 GnomeVFSFileSize allowed_size)
2348 GnomeVFSHandle *handle = NULL;
2349 ModestMsgEditWindowPrivate *priv;
2350 GnomeVFSResult result;
2351 GnomeVFSFileSize size = 0;
2352 g_return_val_if_fail (window, 0);
2353 g_return_val_if_fail (uri, 0);
2355 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2357 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2358 if (result == GNOME_VFS_OK) {
2359 TnyMimePart *mime_part;
2361 const gchar *mime_type = NULL;
2363 gchar *escaped_filename;
2366 GnomeVFSFileInfo *info;
2367 GnomeVFSURI *vfs_uri;
2369 gnome_vfs_close (handle);
2370 vfs_uri = gnome_vfs_uri_new (uri);
2373 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2374 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2375 g_free (escaped_filename);
2376 gnome_vfs_uri_unref (vfs_uri);
2378 info = gnome_vfs_file_info_new ();
2380 if (gnome_vfs_get_file_info (uri,
2382 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2384 mime_type = gnome_vfs_file_info_get_mime_type (info);
2385 mime_part = tny_platform_factory_new_mime_part
2386 (modest_runtime_get_platform_factory ());
2388 /* try to get the attachment's size; this may fail for weird
2389 * file systems, like obex, upnp... */
2390 if (allowed_size != 0 &&
2391 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2393 if (size > allowed_size) {
2394 modest_platform_information_banner (NULL, NULL,
2395 _FM("sfil_ib_opening_not_allowed"));
2400 g_warning ("%s: could not get attachment size", __FUNCTION__);
2402 stream = create_stream_for_uri (uri);
2404 if (stream == NULL) {
2406 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2408 g_object_unref (mime_part);
2410 gnome_vfs_file_info_unref (info);
2414 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2415 g_object_unref (stream);
2417 content_id = g_strdup_printf ("%d", priv->next_cid);
2418 tny_mime_part_set_content_id (mime_part, content_id);
2419 g_free (content_id);
2422 basename = g_path_get_basename (filename);
2423 tny_mime_part_set_filename (mime_part, basename);
2426 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2427 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2429 info->size == 0, info->size);
2430 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2431 gtk_widget_show_all (priv->attachments_caption);
2432 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2434 g_object_unref (mime_part);
2435 gnome_vfs_file_info_unref (info);
2442 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2445 ModestMsgEditWindowPrivate *priv;
2448 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2449 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2451 if (att_list == NULL) {
2452 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2453 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2454 g_object_unref (att_list);
2459 g_object_ref (att_list);
2462 if (tny_list_get_length (att_list) == 0) {
2463 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2465 gboolean dialog_response;
2466 gchar *message = NULL;
2467 gchar *filename = NULL;
2469 if (tny_list_get_length (att_list) == 1) {
2471 iter = tny_list_create_iterator (att_list);
2472 part = (TnyMimePart *) tny_iterator_get_current (iter);
2473 g_object_unref (iter);
2474 if (TNY_IS_MSG (part)) {
2475 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2477 filename = tny_header_dup_subject (header);
2478 g_object_unref (header);
2480 if (filename == NULL) {
2481 filename = g_strdup (_("mail_va_no_subject"));
2484 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2486 g_object_unref (part);
2488 filename = g_strdup ("");
2490 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2491 "emev_nc_delete_attachments",
2492 tny_list_get_length (att_list)), filename);
2495 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2499 if (dialog_response != GTK_RESPONSE_OK) {
2500 g_object_unref (att_list);
2504 for (iter = tny_list_create_iterator (att_list);
2505 !tny_iterator_is_done (iter);
2506 tny_iterator_next (iter)) {
2507 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2508 const gchar *att_id;
2509 tny_list_remove (priv->attachments, (GObject *) mime_part);
2511 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2513 if (tny_list_get_length (priv->attachments) == 0)
2514 gtk_widget_hide (priv->attachments_caption);
2515 att_id = tny_mime_part_get_content_id (mime_part);
2517 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2519 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2520 g_object_unref (mime_part);
2522 g_object_unref (iter);
2525 g_object_unref (att_list);
2527 /* if the last attachment has been removed, focus the Subject: field */
2528 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2529 gtk_widget_grab_focus (priv->subject_field);
2533 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2536 ModestMsgEditWindowPrivate *priv;
2537 GdkColor *new_color;
2538 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2540 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2541 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2544 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2546 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2548 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2550 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2555 font_size_clicked (GtkToolButton *button,
2556 ModestMsgEditWindow *window)
2558 ModestMsgEditWindowPrivate *priv;
2559 GtkWidget *selector, *dialog;
2561 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2563 selector = hildon_touch_selector_new ();
2564 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2565 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2567 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2568 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2570 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2574 WPTextBufferFormat format;
2576 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2578 memset (&format, 0, sizeof (format));
2579 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2581 format.cs.font_size = TRUE;
2582 format.cs.text_position = TRUE;
2583 format.cs.font = TRUE;
2584 format.font_size = new_index;
2585 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2587 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2588 GINT_TO_POINTER (new_index)))
2589 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2591 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2592 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2593 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2594 size_text, "</span>", NULL);
2596 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2600 gtk_widget_destroy (dialog);
2602 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2607 font_face_clicked (GtkToolButton *button,
2608 ModestMsgEditWindow *window)
2610 ModestMsgEditWindowPrivate *priv;
2611 GtkWidget *selector, *dialog;
2612 GtkCellRenderer *renderer;
2614 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2616 selector = hildon_touch_selector_new ();
2617 renderer = gtk_cell_renderer_text_new ();
2618 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2619 renderer, "family", 0, "text", 0, NULL);
2620 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2622 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2623 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2625 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2626 gint new_font_index;
2630 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2631 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2632 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2636 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2638 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2639 GINT_TO_POINTER(new_font_index)))
2640 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2642 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2643 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2645 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2649 gtk_tree_path_free (path);
2652 gtk_widget_destroy (dialog);
2654 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2659 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2662 ModestMsgEditWindowPrivate *priv = NULL;
2663 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2665 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2666 if (!priv->update_caption_visibility)
2669 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2671 gtk_widget_show (priv->cc_caption);
2673 gtk_widget_hide (priv->cc_caption);
2675 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2679 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2682 ModestMsgEditWindowPrivate *priv = NULL;
2683 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2685 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2686 if (!priv->update_caption_visibility)
2689 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2691 gtk_widget_show (priv->bcc_caption);
2693 gtk_widget_hide (priv->bcc_caption);
2695 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2699 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2700 ModestRecptEditor *editor)
2702 ModestMsgEditWindowPrivate *priv;
2704 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2705 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2707 /* we check for low-mem; in that case, show a warning, and don't allow
2708 * for the addressbook
2710 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2713 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2715 if (editor == NULL) {
2716 GtkWidget *view_focus;
2717 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2719 /* This code should be kept in sync with ModestRecptEditor. The
2720 textview inside the recpt editor is the one that really gets the
2721 focus. As it's inside a scrolled window, and this one inside the
2722 hbox recpt editor inherits from, we'll need to go up in the
2723 hierarchy to know if the text view is part of the recpt editor
2724 or if it's a different text entry */
2726 if (gtk_widget_get_parent (view_focus)) {
2727 GtkWidget *first_parent;
2729 first_parent = gtk_widget_get_parent (view_focus);
2730 if (gtk_widget_get_parent (first_parent) &&
2731 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2732 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2737 editor = MODEST_RECPT_EDITOR (priv->to_field);
2741 modest_address_book_select_addresses (editor);
2746 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2748 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2750 modest_msg_edit_window_open_addressbook (window, NULL);
2754 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2755 gboolean show_toolbar)
2757 ModestWindowPrivate *parent_priv;
2759 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2760 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2762 /* We can not just use the code of
2763 modest_msg_edit_window_setup_toolbar because it has a
2764 mixture of both initialization and creation code. */
2766 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2768 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2772 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2773 TnyHeaderFlags priority_flags)
2775 ModestMsgEditWindowPrivate *priv;
2776 ModestWindowPrivate *parent_priv;
2778 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2780 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2781 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2783 if (priv->priority_flags != priority_flags) {
2784 GtkAction *priority_action = NULL;
2786 priv->priority_flags = priority_flags;
2788 switch (priority_flags) {
2789 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2790 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2791 MODEST_HEADER_ICON_HIGH,
2792 HILDON_ICON_SIZE_SMALL);
2793 gtk_widget_show (priv->priority_icon);
2794 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2795 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2797 case TNY_HEADER_FLAG_LOW_PRIORITY:
2798 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2799 MODEST_HEADER_ICON_LOW,
2800 HILDON_ICON_SIZE_SMALL);
2801 gtk_widget_show (priv->priority_icon);
2802 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2803 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2806 gtk_widget_hide (priv->priority_icon);
2807 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2808 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2811 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2812 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2814 gtk_widget_queue_resize (priv->subject_box);
2818 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2821 ModestMsgEditWindowPrivate *priv;
2822 ModestWindowPrivate *parent_priv;
2823 gint current_format;
2825 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2827 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2828 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2830 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2831 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2833 if (current_format != file_format) {
2834 switch (file_format) {
2835 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2836 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2837 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2839 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2843 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2844 response = gtk_dialog_run (GTK_DIALOG (dialog));
2845 gtk_widget_destroy (dialog);
2846 if (response == GTK_RESPONSE_OK) {
2847 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2849 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2850 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2855 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2856 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2857 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2862 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2865 ModestMsgEditWindowPrivate *priv;
2866 WPTextBufferFormat oldfmt, fmt;
2867 gint old_position = 0;
2871 GdkColor *color = NULL;
2872 gboolean bold, bold_set, italic, italic_set;
2873 gboolean underline, underline_set;
2874 gboolean strikethrough, strikethrough_set;
2875 gboolean position_set;
2876 gboolean font_size_set, font_set, color_set;
2879 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2880 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2882 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2883 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2884 GTK_WINDOW(dialog), GTK_WINDOW (window));
2886 /* First we get the currently selected font information */
2887 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2889 switch (oldfmt.text_position) {
2890 case TEXT_POSITION_NORMAL:
2893 case TEXT_POSITION_SUPERSCRIPT:
2901 g_object_set (G_OBJECT (dialog),
2902 "bold", oldfmt.bold != FALSE,
2903 "bold-set", !oldfmt.cs.bold,
2904 "underline", oldfmt.underline != FALSE,
2905 "underline-set", !oldfmt.cs.underline,
2906 "italic", oldfmt.italic != FALSE,
2907 "italic-set", !oldfmt.cs.italic,
2908 "strikethrough", oldfmt.strikethrough != FALSE,
2909 "strikethrough-set", !oldfmt.cs.strikethrough,
2910 "color", &oldfmt.color,
2911 "color-set", !oldfmt.cs.color,
2912 "size", wp_font_size[oldfmt.font_size],
2913 "size-set", !oldfmt.cs.font_size,
2914 "position", old_position,
2915 "position-set", !oldfmt.cs.text_position,
2916 "family", wp_get_font_name (oldfmt.font),
2917 "family-set", !oldfmt.cs.font,
2920 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2921 GTK_WINDOW (dialog), GTK_WINDOW (window));
2922 gtk_widget_show_all (dialog);
2923 priv->font_dialog = dialog;
2924 response = gtk_dialog_run (GTK_DIALOG (dialog));
2925 priv->font_dialog = NULL;
2926 if (response == GTK_RESPONSE_OK) {
2928 g_object_get( dialog,
2930 "bold-set", &bold_set,
2931 "underline", &underline,
2932 "underline-set", &underline_set,
2934 "italic-set", &italic_set,
2935 "strikethrough", &strikethrough,
2936 "strikethrough-set", &strikethrough_set,
2938 "color-set", &color_set,
2940 "size-set", &font_size_set,
2941 "family", &font_name,
2942 "family-set", &font_set,
2943 "position", &position,
2944 "position-set", &position_set,
2949 if (response == GTK_RESPONSE_OK) {
2950 memset(&fmt, 0, sizeof(fmt));
2956 fmt.italic = italic;
2957 fmt.cs.italic = TRUE;
2959 if (underline_set) {
2960 fmt.underline = underline;
2961 fmt.cs.underline = TRUE;
2963 if (strikethrough_set) {
2964 fmt.strikethrough = strikethrough;
2965 fmt.cs.strikethrough = TRUE;
2970 ? TEXT_POSITION_NORMAL
2971 : ( ( position == 1 )
2972 ? TEXT_POSITION_SUPERSCRIPT
2973 : TEXT_POSITION_SUBSCRIPT );
2974 fmt.cs.text_position = TRUE;
2975 fmt.font_size = oldfmt.font_size;
2979 fmt.cs.color = TRUE;
2982 fmt.font = wp_get_font_index(font_name,
2987 if (font_size_set) {
2988 fmt.cs.font_size = TRUE;
2989 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2991 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2992 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2994 gtk_widget_destroy (dialog);
2996 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3000 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3002 ModestMsgEditWindowPrivate *priv;
3004 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3005 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3007 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3009 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3010 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3014 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3016 ModestMsgEditWindowPrivate *priv;
3018 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3019 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3021 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3023 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3024 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3029 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3031 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3033 priv->can_undo = can_undo;
3037 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3039 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3041 priv->can_redo = can_redo;
3045 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3047 ModestMsgEditWindowPrivate *priv;
3048 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3049 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3051 return priv->can_undo;
3055 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3057 ModestMsgEditWindowPrivate *priv;
3058 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3059 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3061 return priv->can_redo;
3066 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3069 GtkTextIter match_start, match_end;
3071 if (image_id == NULL)
3074 gtk_text_buffer_get_start_iter (buffer, &iter);
3076 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3077 GSList *tags = gtk_text_iter_get_tags (&match_start);
3079 for (node = tags; node != NULL; node = g_slist_next (node)) {
3080 GtkTextTag *tag = (GtkTextTag *) node->data;
3081 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3082 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3083 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3085 offset = gtk_text_iter_get_offset (&match_start);
3086 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3087 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3091 gtk_text_iter_forward_char (&iter);
3096 message_is_empty (ModestMsgEditWindow *window)
3098 ModestMsgEditWindowPrivate *priv = NULL;
3100 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3101 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3103 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3104 * so we can ignore markup.
3106 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3109 count = gtk_text_buffer_get_char_count (buf);
3115 msg_body_focus (GtkWidget *focus,
3116 GdkEventFocus *event,
3120 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3121 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3122 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3127 recpt_field_changed (GtkTextBuffer *buffer,
3128 ModestMsgEditWindow *editor)
3130 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3131 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3135 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3137 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3138 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3142 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3145 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3146 GtkTextBuffer *buffer;
3148 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3149 gtk_text_buffer_set_modified (buffer, modified);
3150 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3151 gtk_text_buffer_set_modified (buffer, modified);
3152 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3153 gtk_text_buffer_set_modified (buffer, modified);
3154 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3158 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3160 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3161 const char *account_name;
3162 GtkTextBuffer *buffer;
3164 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3165 if (gtk_text_buffer_get_modified (buffer))
3167 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3168 if (gtk_text_buffer_get_modified (buffer))
3170 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3171 if (gtk_text_buffer_get_modified (buffer))
3173 if (gtk_text_buffer_get_modified (priv->text_buffer))
3175 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3176 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3187 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3189 ModestMsgEditWindowPrivate *priv = NULL;
3191 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3192 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3194 /* check if there's no recipient added */
3195 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3196 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3197 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3198 /* no recipient contents, then select contacts */
3199 modest_msg_edit_window_open_addressbook (window, NULL);
3203 g_object_ref (window);
3204 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3205 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3206 g_object_unref (window);
3209 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3210 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3211 g_object_unref (window);
3214 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3215 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3216 g_object_unref (window);
3220 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3221 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3222 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3223 g_object_unref (window);
3230 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3231 ModestMsgEditWindow *window)
3233 modest_msg_edit_window_offer_attach_file (window);
3237 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3239 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3241 return priv->clipboard_text;
3245 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3247 ModestMsgEditWindow *window)
3249 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3250 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3253 /* It could happen that the window was already closed */
3254 if (!GTK_WIDGET_VISIBLE (window))
3257 g_object_ref (window);
3258 text = gtk_clipboard_wait_for_text (selection_clipboard);
3260 if (priv->clipboard_text != NULL) {
3261 g_free (priv->clipboard_text);
3263 priv->clipboard_text = text;
3265 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3267 g_object_unref (window);
3270 static gboolean clipboard_owner_change_idle (gpointer userdata)
3272 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3273 ModestMsgEditWindowPrivate *priv;
3275 gdk_threads_enter ();
3276 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3277 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3279 priv->clipboard_owner_idle = 0;
3280 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3281 gdk_threads_leave ();
3287 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3289 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3290 if (priv->clipboard_owner_idle == 0) {
3291 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3292 clipboard_owner_change_idle,
3293 g_object_ref (window),
3299 subject_field_move_cursor (GtkEntry *entry,
3300 GtkMovementStep step,
3305 /* It could happen that the window was already closed */
3306 if (!GTK_WIDGET_VISIBLE (window))
3309 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3313 update_window_title (ModestMsgEditWindow *window)
3315 ModestMsgEditWindowPrivate *priv = NULL;
3316 const gchar *subject;
3318 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3319 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3320 if (subject == NULL || subject[0] == '\0')
3321 subject = _("mail_va_new_email");
3323 gtk_window_set_title (GTK_WINDOW (window), subject);
3328 subject_field_changed (GtkEditable *editable,
3329 ModestMsgEditWindow *window)
3331 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3332 update_window_title (window);
3333 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3334 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3335 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3339 subject_field_insert_text (GtkEditable *editable,
3341 gint new_text_length,
3343 ModestMsgEditWindow *window)
3345 GString *result = g_string_new ("");
3347 gint result_len = 0;
3348 const gchar *entry_text = NULL;
3351 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3352 old_length = g_utf8_strlen (entry_text, -1);
3354 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3355 gunichar c = g_utf8_get_char_validated (current, 8);
3356 /* Invalid unichar, stop */
3362 result = g_string_append_unichar (result, c);
3366 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3367 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3370 /* Prevent endless recursion */
3371 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3372 g_signal_emit_by_name (editable, "insert-text",
3373 (gpointer) result->str, (gpointer) result->len,
3374 (gpointer) position, (gpointer) window);
3375 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3379 if (result_len + old_length > 1000) {
3380 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3381 _CS("ckdg_ib_maximum_characters_reached"));
3383 g_string_free (result, TRUE);
3387 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3390 ModestMsgEditWindowPrivate *priv = NULL;
3392 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3393 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3395 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3398 gtk_widget_show_all (priv->find_toolbar);
3399 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3401 gtk_widget_hide_all (priv->find_toolbar);
3402 gtk_widget_grab_focus (priv->msg_body);
3407 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3409 GtkTextIter *match_start,
3410 GtkTextIter *match_end)
3412 GtkTextIter end_iter;
3413 gchar *str_casefold;
3416 gchar *range_casefold;
3419 gboolean result = FALSE;
3426 gtk_text_iter_forward_to_end (&end_iter);
3428 str_casefold = g_utf8_casefold (str, -1);
3429 str_chars_n = strlen (str);
3431 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3432 range_casefold = g_utf8_casefold (range_text, -1);
3433 range_chars_n = strlen (range_casefold);
3435 if (range_chars_n < str_chars_n) {
3436 g_free (str_casefold);
3437 g_free (range_text);
3438 g_free (range_casefold);
3442 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3443 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3444 if (!g_utf8_collate (range_subtext, str_casefold)) {
3445 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3447 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3448 match_start, match_end, NULL);
3449 g_free (found_text);
3451 g_free (range_subtext);
3455 g_free (str_casefold);
3456 g_free (range_text);
3457 g_free (range_casefold);
3464 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3465 ModestMsgEditWindow *window)
3467 gchar *current_search = NULL;
3468 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3470 GtkTextIter selection_start, selection_end;
3471 GtkTextIter match_start, match_end;
3472 gboolean continue_search = FALSE;
3474 if (message_is_empty (window)) {
3475 g_free (priv->last_search);
3476 priv->last_search = NULL;
3477 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3481 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3482 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3483 g_free (current_search);
3484 g_free (priv->last_search);
3485 priv->last_search = NULL;
3486 /* Information banner about empty search */
3487 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3491 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3492 continue_search = TRUE;
3494 g_free (priv->last_search);
3495 priv->last_search = g_strdup (current_search);
3498 if (continue_search) {
3499 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3500 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3501 &match_start, &match_end);
3503 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3505 GtkTextIter buffer_start;
3506 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3507 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3508 &match_start, &match_end);
3510 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3513 /* Mark as selected the string found in search */
3515 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3516 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3517 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3519 g_free (priv->last_search);
3520 priv->last_search = NULL;
3522 g_free (current_search);
3526 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3528 ModestMsgEditWindowPrivate *priv;
3530 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3535 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3538 ModestMsgEditWindowPrivate *priv;
3540 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3545 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3546 ModestMsgEditWindow *window)
3548 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3552 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3555 ModestMsgEditWindowPrivate *priv;
3556 TnyHeader *header = NULL;
3558 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3559 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3561 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3562 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3564 if (priv->draft_msg != NULL) {
3565 g_object_unref (priv->draft_msg);
3568 if (draft != NULL) {
3569 g_object_ref (draft);
3570 header = tny_msg_get_header (draft);
3571 if (priv->msg_uid) {
3572 g_free (priv->msg_uid);
3573 priv->msg_uid = NULL;
3575 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3576 if (GTK_WIDGET_REALIZED (window)) {
3577 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3578 gtk_widget_destroy (GTK_WIDGET (window));
3584 priv->draft_msg = draft;
3588 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3589 GtkTextIter *start, GtkTextIter *end,
3592 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3593 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3596 if (tag == NULL) return;
3597 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3598 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3599 replace_with_images (window, priv->images);
3604 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3607 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3609 g_return_if_fail (TNY_IS_MIME_PART (part));
3610 tny_list_prepend (priv->attachments, (GObject *) part);
3611 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3612 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3613 gtk_widget_show_all (priv->attachments_caption);
3614 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3618 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3620 ModestMsgEditWindowPrivate *priv;
3622 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3623 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3625 return priv->msg_uid;
3629 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3630 ModestMsgEditWindowWidgetType widget_type)
3632 ModestMsgEditWindowPrivate *priv;
3634 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3635 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3637 switch (widget_type) {
3638 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3639 return priv->msg_body;
3641 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3642 return priv->to_field;
3644 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3645 return priv->cc_field;
3647 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3648 return priv->bcc_field;
3650 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3651 return priv->subject_field;
3653 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3654 return priv->attachments_view;
3662 remove_tags (WPTextBuffer *buffer)
3664 GtkTextIter start, end;
3666 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3667 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3669 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3673 on_account_removed (TnyAccountStore *account_store,
3674 TnyAccount *account,
3677 /* Do nothing if it's a store account, because we use the
3678 transport to send the messages */
3679 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3680 const gchar *parent_acc = NULL;
3681 const gchar *our_acc = NULL;
3683 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3684 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3685 /* Close this window if I'm showing a message of the removed account */
3686 if (strcmp (parent_acc, our_acc) == 0)
3687 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3692 from_field_changed (HildonPickerButton *button,
3693 ModestMsgEditWindow *self)
3695 ModestMsgEditWindowPrivate *priv;
3696 gboolean has_old_signature, has_new_signature;
3698 GtkTextIter match_start, match_end;
3699 ModestAccountMgr *mgr;
3701 gchar *full_signature;
3703 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3705 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3706 mgr = modest_runtime_get_account_mgr ();
3707 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3708 if (has_old_signature) {
3709 full_signature = g_strconcat ("\n--\n", signature, NULL);
3710 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3711 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3713 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3714 &match_start, &match_end, NULL)) {
3717 g_free (full_signature);
3721 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3722 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3723 if (has_new_signature) {
3724 full_signature = g_strconcat ("\n--\n", signature, NULL);
3725 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3726 g_free (full_signature);
3731 typedef struct _MessageSettingsHelper {
3732 ModestMsgEditWindow *window;
3733 GSList *priority_group;
3734 GSList *format_group;
3735 GtkToggleButton *current_priority;
3736 GtkToggleButton *current_format;
3737 } MessageSettingsHelper;
3740 on_priority_toggle (GtkToggleButton *button,
3741 MessageSettingsHelper *helper)
3744 ModestMsgEditWindowPrivate *priv;
3746 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3747 if (gtk_toggle_button_get_active (button)) {
3749 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3750 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3751 if ((node_button != button) &&
3752 gtk_toggle_button_get_active (node_button)) {
3753 gtk_toggle_button_set_active (node_button, FALSE);
3756 helper->current_priority = button;
3758 gboolean found = FALSE;
3759 /* If no one is active, activate it again */
3760 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3761 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3762 if (gtk_toggle_button_get_active (node_button)) {
3768 gtk_toggle_button_set_active (button, TRUE);
3774 on_format_toggle (GtkToggleButton *button,
3775 MessageSettingsHelper *helper)
3778 ModestMsgEditWindowPrivate *priv;
3780 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3781 if (gtk_toggle_button_get_active (button)) {
3783 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3784 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3785 if ((node_button != button) &&
3786 gtk_toggle_button_get_active (node_button)) {
3787 gtk_toggle_button_set_active (node_button, FALSE);
3790 helper->current_format = button;
3792 gboolean found = FALSE;
3793 /* If no one is active, activate it again */
3794 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3795 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3796 if (gtk_toggle_button_get_active (node_button)) {
3802 gtk_toggle_button_set_active (button, TRUE);
3809 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3814 GtkWidget *priority_hbox;
3815 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3816 GtkWidget *captioned;
3817 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3818 GtkWidget *format_hbox;
3819 GtkWidget *html_toggle, *text_toggle;
3820 ModestMsgEditWindowPrivate *priv;
3821 MessageSettingsHelper helper = {0,};
3823 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3824 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3825 helper.window = window;
3826 helper.priority_group = NULL;
3827 helper.format_group = NULL;
3829 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3830 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3832 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3833 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3834 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3835 vbox = gtk_vbox_new (FALSE, 0);
3836 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
3837 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
3838 gtk_container_add (GTK_CONTAINER (align), vbox);
3839 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
3840 gtk_widget_show (align);
3841 gtk_widget_show (vbox);
3843 /* Priority toggles */
3844 priority_hbox = gtk_hbox_new (TRUE, 0);
3845 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3846 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3847 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3848 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3849 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3850 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3851 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3852 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3853 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3854 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3855 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3856 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3857 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3858 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3859 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3860 gtk_widget_show_all (priority_hbox);
3861 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3862 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3863 gtk_widget_show (captioned);
3864 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3866 /* format toggles */
3867 format_hbox = gtk_hbox_new (TRUE, 0);
3868 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3869 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3870 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3871 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3872 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3873 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3874 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3875 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3876 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3877 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3878 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3879 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3880 gtk_widget_show_all (format_hbox);
3881 gtk_widget_show (format_hbox);
3882 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3885 g_object_unref (title_sizegroup);
3886 g_object_unref (value_sizegroup);
3888 /* Set current values */
3889 switch (priv->priority_flags) {
3890 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3891 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3892 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3894 case TNY_HEADER_FLAG_LOW_PRIORITY:
3895 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3896 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3899 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3900 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3904 switch (modest_msg_edit_window_get_format (window)) {
3905 case MODEST_MSG_EDIT_FORMAT_TEXT:
3906 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3907 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3909 case MODEST_MSG_EDIT_FORMAT_HTML:
3911 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3912 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3916 /* Signal connects */
3917 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3918 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3919 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3920 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3921 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3923 /* Save settings if the user clicked on done */
3924 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3925 TnyHeaderFlags flags;
3926 ModestMsgEditFormat old_format, new_format;
3928 /* Set priority flags */
3929 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3930 if (priv->priority_flags != flags)
3931 modest_msg_edit_window_set_priority_flags (window, flags);
3933 /* Set edit format */
3934 old_format = modest_msg_edit_window_get_format (window);
3935 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3936 if (old_format != new_format) {
3937 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3938 modest_msg_edit_window_set_file_format (window, file_format);
3942 gtk_widget_destroy (dialog);
3943 g_slist_free (helper.priority_group);
3947 on_message_settings (GtkAction *action,
3948 ModestMsgEditWindow *window)
3950 modest_msg_edit_window_show_msg_settings_dialog (window);
3954 on_cc_button_toggled (HildonCheckButton *button,
3955 ModestMsgEditWindow *window)
3957 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3959 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3960 hildon_check_button_get_active (button));
3964 on_bcc_button_toggled (HildonCheckButton *button,
3965 ModestMsgEditWindow *window)
3967 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3969 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3970 hildon_check_button_get_active (button));
3974 setup_menu (ModestMsgEditWindow *self)
3976 ModestMsgEditWindowPrivate *priv = NULL;
3978 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3980 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3982 /* Settings menu buttons */
3983 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3984 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3986 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3987 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3988 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3990 priv->cc_button = hildon_check_button_new (0);
3991 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3992 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3994 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3996 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3997 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3998 priv->bcc_button = hildon_check_button_new (0);
3999 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4000 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4002 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4004 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4005 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4007 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4008 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4009 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4010 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4011 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4012 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4013 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4014 APP_MENU_CALLBACK (on_message_settings),
4016 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4017 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),