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));
2569 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2571 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2575 WPTextBufferFormat format;
2577 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2579 memset (&format, 0, sizeof (format));
2580 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2582 format.cs.font_size = TRUE;
2583 format.cs.text_position = TRUE;
2584 format.cs.font = TRUE;
2585 format.font_size = new_index;
2586 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2588 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2589 GINT_TO_POINTER (new_index)))
2590 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2592 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2593 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2594 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2595 size_text, "</span>", NULL);
2597 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2601 gtk_widget_destroy (dialog);
2603 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2608 font_face_clicked (GtkToolButton *button,
2609 ModestMsgEditWindow *window)
2611 ModestMsgEditWindowPrivate *priv;
2612 GtkWidget *selector, *dialog;
2613 GtkCellRenderer *renderer;
2615 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2617 selector = hildon_touch_selector_new ();
2618 renderer = gtk_cell_renderer_text_new ();
2619 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2620 renderer, "family", 0, "text", 0, NULL);
2621 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2623 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2624 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2625 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2627 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2628 gint new_font_index;
2632 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2633 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2634 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2638 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2640 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2641 GINT_TO_POINTER(new_font_index)))
2642 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2644 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2645 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2647 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2651 gtk_tree_path_free (path);
2654 gtk_widget_destroy (dialog);
2656 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2661 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2664 ModestMsgEditWindowPrivate *priv = NULL;
2665 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2667 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2668 if (!priv->update_caption_visibility)
2671 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2673 gtk_widget_show (priv->cc_caption);
2675 gtk_widget_hide (priv->cc_caption);
2677 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2681 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2684 ModestMsgEditWindowPrivate *priv = NULL;
2685 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2687 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2688 if (!priv->update_caption_visibility)
2691 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2693 gtk_widget_show (priv->bcc_caption);
2695 gtk_widget_hide (priv->bcc_caption);
2697 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2701 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2702 ModestRecptEditor *editor)
2704 ModestMsgEditWindowPrivate *priv;
2706 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2707 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2709 /* we check for low-mem; in that case, show a warning, and don't allow
2710 * for the addressbook
2712 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2715 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2717 if (editor == NULL) {
2718 GtkWidget *view_focus;
2719 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2721 /* This code should be kept in sync with ModestRecptEditor. The
2722 textview inside the recpt editor is the one that really gets the
2723 focus. As it's inside a scrolled window, and this one inside the
2724 hbox recpt editor inherits from, we'll need to go up in the
2725 hierarchy to know if the text view is part of the recpt editor
2726 or if it's a different text entry */
2728 if (gtk_widget_get_parent (view_focus)) {
2729 GtkWidget *first_parent;
2731 first_parent = gtk_widget_get_parent (view_focus);
2732 if (gtk_widget_get_parent (first_parent) &&
2733 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2734 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2739 editor = MODEST_RECPT_EDITOR (priv->to_field);
2743 modest_address_book_select_addresses (editor);
2748 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2750 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2752 modest_msg_edit_window_open_addressbook (window, NULL);
2756 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2757 gboolean show_toolbar)
2759 ModestWindowPrivate *parent_priv;
2761 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2762 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2764 /* We can not just use the code of
2765 modest_msg_edit_window_setup_toolbar because it has a
2766 mixture of both initialization and creation code. */
2768 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2770 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2774 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2775 TnyHeaderFlags priority_flags)
2777 ModestMsgEditWindowPrivate *priv;
2778 ModestWindowPrivate *parent_priv;
2780 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2782 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2783 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2785 if (priv->priority_flags != priority_flags) {
2786 GtkAction *priority_action = NULL;
2788 priv->priority_flags = priority_flags;
2790 switch (priority_flags) {
2791 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2792 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2793 MODEST_HEADER_ICON_HIGH,
2794 HILDON_ICON_SIZE_SMALL);
2795 gtk_widget_show (priv->priority_icon);
2796 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2797 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2799 case TNY_HEADER_FLAG_LOW_PRIORITY:
2800 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2801 MODEST_HEADER_ICON_LOW,
2802 HILDON_ICON_SIZE_SMALL);
2803 gtk_widget_show (priv->priority_icon);
2804 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2805 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2808 gtk_widget_hide (priv->priority_icon);
2809 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2810 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2813 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2814 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2816 gtk_widget_queue_resize (priv->subject_box);
2820 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2823 ModestMsgEditWindowPrivate *priv;
2824 ModestWindowPrivate *parent_priv;
2825 gint current_format;
2827 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2829 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2830 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2832 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2833 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2835 if (current_format != file_format) {
2836 switch (file_format) {
2837 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2838 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2839 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2841 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2845 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2846 response = gtk_dialog_run (GTK_DIALOG (dialog));
2847 gtk_widget_destroy (dialog);
2848 if (response == GTK_RESPONSE_OK) {
2849 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2851 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2852 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2857 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2858 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2859 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2864 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2867 ModestMsgEditWindowPrivate *priv;
2868 WPTextBufferFormat oldfmt, fmt;
2869 gint old_position = 0;
2873 GdkColor *color = NULL;
2874 gboolean bold, bold_set, italic, italic_set;
2875 gboolean underline, underline_set;
2876 gboolean strikethrough, strikethrough_set;
2877 gboolean position_set;
2878 gboolean font_size_set, font_set, color_set;
2881 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2882 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2884 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2885 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2886 GTK_WINDOW(dialog), GTK_WINDOW (window));
2888 /* First we get the currently selected font information */
2889 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2891 switch (oldfmt.text_position) {
2892 case TEXT_POSITION_NORMAL:
2895 case TEXT_POSITION_SUPERSCRIPT:
2903 g_object_set (G_OBJECT (dialog),
2904 "bold", oldfmt.bold != FALSE,
2905 "bold-set", !oldfmt.cs.bold,
2906 "underline", oldfmt.underline != FALSE,
2907 "underline-set", !oldfmt.cs.underline,
2908 "italic", oldfmt.italic != FALSE,
2909 "italic-set", !oldfmt.cs.italic,
2910 "strikethrough", oldfmt.strikethrough != FALSE,
2911 "strikethrough-set", !oldfmt.cs.strikethrough,
2912 "color", &oldfmt.color,
2913 "color-set", !oldfmt.cs.color,
2914 "size", wp_font_size[oldfmt.font_size],
2915 "size-set", !oldfmt.cs.font_size,
2916 "position", old_position,
2917 "position-set", !oldfmt.cs.text_position,
2918 "family", wp_get_font_name (oldfmt.font),
2919 "family-set", !oldfmt.cs.font,
2922 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2923 GTK_WINDOW (dialog), GTK_WINDOW (window));
2924 gtk_widget_show_all (dialog);
2925 priv->font_dialog = dialog;
2926 response = gtk_dialog_run (GTK_DIALOG (dialog));
2927 priv->font_dialog = NULL;
2928 if (response == GTK_RESPONSE_OK) {
2930 g_object_get( dialog,
2932 "bold-set", &bold_set,
2933 "underline", &underline,
2934 "underline-set", &underline_set,
2936 "italic-set", &italic_set,
2937 "strikethrough", &strikethrough,
2938 "strikethrough-set", &strikethrough_set,
2940 "color-set", &color_set,
2942 "size-set", &font_size_set,
2943 "family", &font_name,
2944 "family-set", &font_set,
2945 "position", &position,
2946 "position-set", &position_set,
2951 if (response == GTK_RESPONSE_OK) {
2952 memset(&fmt, 0, sizeof(fmt));
2958 fmt.italic = italic;
2959 fmt.cs.italic = TRUE;
2961 if (underline_set) {
2962 fmt.underline = underline;
2963 fmt.cs.underline = TRUE;
2965 if (strikethrough_set) {
2966 fmt.strikethrough = strikethrough;
2967 fmt.cs.strikethrough = TRUE;
2972 ? TEXT_POSITION_NORMAL
2973 : ( ( position == 1 )
2974 ? TEXT_POSITION_SUPERSCRIPT
2975 : TEXT_POSITION_SUBSCRIPT );
2976 fmt.cs.text_position = TRUE;
2977 fmt.font_size = oldfmt.font_size;
2981 fmt.cs.color = TRUE;
2984 fmt.font = wp_get_font_index(font_name,
2989 if (font_size_set) {
2990 fmt.cs.font_size = TRUE;
2991 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2993 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2994 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2996 gtk_widget_destroy (dialog);
2998 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3002 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3004 ModestMsgEditWindowPrivate *priv;
3006 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3007 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3009 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3011 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3012 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3016 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3018 ModestMsgEditWindowPrivate *priv;
3020 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3021 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3023 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3025 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3026 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3031 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3033 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3035 priv->can_undo = can_undo;
3039 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3041 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3043 priv->can_redo = can_redo;
3047 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3049 ModestMsgEditWindowPrivate *priv;
3050 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3051 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3053 return priv->can_undo;
3057 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3059 ModestMsgEditWindowPrivate *priv;
3060 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3061 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3063 return priv->can_redo;
3068 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3071 GtkTextIter match_start, match_end;
3073 if (image_id == NULL)
3076 gtk_text_buffer_get_start_iter (buffer, &iter);
3078 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3079 GSList *tags = gtk_text_iter_get_tags (&match_start);
3081 for (node = tags; node != NULL; node = g_slist_next (node)) {
3082 GtkTextTag *tag = (GtkTextTag *) node->data;
3083 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3084 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3085 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3087 offset = gtk_text_iter_get_offset (&match_start);
3088 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3089 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3093 gtk_text_iter_forward_char (&iter);
3098 message_is_empty (ModestMsgEditWindow *window)
3100 ModestMsgEditWindowPrivate *priv = NULL;
3102 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3103 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3105 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3106 * so we can ignore markup.
3108 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3111 count = gtk_text_buffer_get_char_count (buf);
3117 msg_body_focus (GtkWidget *focus,
3118 GdkEventFocus *event,
3122 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3123 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3124 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3129 recpt_field_changed (GtkTextBuffer *buffer,
3130 ModestMsgEditWindow *editor)
3132 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3133 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3137 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3139 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3140 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3144 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3147 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3148 GtkTextBuffer *buffer;
3150 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3151 gtk_text_buffer_set_modified (buffer, modified);
3152 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3153 gtk_text_buffer_set_modified (buffer, modified);
3154 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3155 gtk_text_buffer_set_modified (buffer, modified);
3156 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3160 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3162 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3163 const char *account_name;
3164 GtkTextBuffer *buffer;
3166 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3167 if (gtk_text_buffer_get_modified (buffer))
3169 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3170 if (gtk_text_buffer_get_modified (buffer))
3172 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3173 if (gtk_text_buffer_get_modified (buffer))
3175 if (gtk_text_buffer_get_modified (priv->text_buffer))
3177 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3178 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3189 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3191 ModestMsgEditWindowPrivate *priv = NULL;
3193 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3194 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3196 /* check if there's no recipient added */
3197 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3198 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3199 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3200 /* no recipient contents, then select contacts */
3201 modest_msg_edit_window_open_addressbook (window, NULL);
3205 g_object_ref (window);
3206 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3207 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3208 g_object_unref (window);
3211 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3212 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3213 g_object_unref (window);
3216 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3217 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3218 g_object_unref (window);
3222 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3223 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3224 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3225 g_object_unref (window);
3232 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3233 ModestMsgEditWindow *window)
3235 modest_msg_edit_window_offer_attach_file (window);
3239 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3241 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3243 return priv->clipboard_text;
3247 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3249 ModestMsgEditWindow *window)
3251 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3252 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3255 /* It could happen that the window was already closed */
3256 if (!GTK_WIDGET_VISIBLE (window))
3259 g_object_ref (window);
3260 text = gtk_clipboard_wait_for_text (selection_clipboard);
3262 if (priv->clipboard_text != NULL) {
3263 g_free (priv->clipboard_text);
3265 priv->clipboard_text = text;
3267 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3269 g_object_unref (window);
3272 static gboolean clipboard_owner_change_idle (gpointer userdata)
3274 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3275 ModestMsgEditWindowPrivate *priv;
3277 gdk_threads_enter ();
3278 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3279 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3281 priv->clipboard_owner_idle = 0;
3282 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3283 gdk_threads_leave ();
3289 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3291 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3292 if (priv->clipboard_owner_idle == 0) {
3293 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3294 clipboard_owner_change_idle,
3295 g_object_ref (window),
3301 subject_field_move_cursor (GtkEntry *entry,
3302 GtkMovementStep step,
3307 /* It could happen that the window was already closed */
3308 if (!GTK_WIDGET_VISIBLE (window))
3311 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3315 update_window_title (ModestMsgEditWindow *window)
3317 ModestMsgEditWindowPrivate *priv = NULL;
3318 const gchar *subject;
3320 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3321 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3322 if (subject == NULL || subject[0] == '\0')
3323 subject = _("mail_va_new_email");
3325 gtk_window_set_title (GTK_WINDOW (window), subject);
3330 subject_field_changed (GtkEditable *editable,
3331 ModestMsgEditWindow *window)
3333 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3334 update_window_title (window);
3335 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3336 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3337 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3341 subject_field_insert_text (GtkEditable *editable,
3343 gint new_text_length,
3345 ModestMsgEditWindow *window)
3347 GString *result = g_string_new ("");
3349 gint result_len = 0;
3350 const gchar *entry_text = NULL;
3353 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3354 old_length = g_utf8_strlen (entry_text, -1);
3356 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3357 gunichar c = g_utf8_get_char_validated (current, 8);
3358 /* Invalid unichar, stop */
3364 result = g_string_append_unichar (result, c);
3368 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3369 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3372 /* Prevent endless recursion */
3373 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3374 g_signal_emit_by_name (editable, "insert-text",
3375 (gpointer) result->str, (gpointer) result->len,
3376 (gpointer) position, (gpointer) window);
3377 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3381 if (result_len + old_length > 1000) {
3382 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3383 _CS("ckdg_ib_maximum_characters_reached"));
3385 g_string_free (result, TRUE);
3389 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3392 ModestMsgEditWindowPrivate *priv = NULL;
3394 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3395 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3397 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3400 gtk_widget_show_all (priv->find_toolbar);
3401 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3403 gtk_widget_hide_all (priv->find_toolbar);
3404 gtk_widget_grab_focus (priv->msg_body);
3409 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3411 GtkTextIter *match_start,
3412 GtkTextIter *match_end)
3414 GtkTextIter end_iter;
3415 gchar *str_casefold;
3418 gchar *range_casefold;
3421 gboolean result = FALSE;
3428 gtk_text_iter_forward_to_end (&end_iter);
3430 str_casefold = g_utf8_casefold (str, -1);
3431 str_chars_n = strlen (str);
3433 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3434 range_casefold = g_utf8_casefold (range_text, -1);
3435 range_chars_n = strlen (range_casefold);
3437 if (range_chars_n < str_chars_n) {
3438 g_free (str_casefold);
3439 g_free (range_text);
3440 g_free (range_casefold);
3444 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3445 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3446 if (!g_utf8_collate (range_subtext, str_casefold)) {
3447 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3449 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3450 match_start, match_end, NULL);
3451 g_free (found_text);
3453 g_free (range_subtext);
3457 g_free (str_casefold);
3458 g_free (range_text);
3459 g_free (range_casefold);
3466 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3467 ModestMsgEditWindow *window)
3469 gchar *current_search = NULL;
3470 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3472 GtkTextIter selection_start, selection_end;
3473 GtkTextIter match_start, match_end;
3474 gboolean continue_search = FALSE;
3476 if (message_is_empty (window)) {
3477 g_free (priv->last_search);
3478 priv->last_search = NULL;
3479 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3483 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3484 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3485 g_free (current_search);
3486 g_free (priv->last_search);
3487 priv->last_search = NULL;
3488 /* Information banner about empty search */
3489 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3493 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3494 continue_search = TRUE;
3496 g_free (priv->last_search);
3497 priv->last_search = g_strdup (current_search);
3500 if (continue_search) {
3501 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3502 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3503 &match_start, &match_end);
3505 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3507 GtkTextIter buffer_start;
3508 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3509 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3510 &match_start, &match_end);
3512 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3515 /* Mark as selected the string found in search */
3517 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3518 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3519 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3521 g_free (priv->last_search);
3522 priv->last_search = NULL;
3524 g_free (current_search);
3528 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3530 ModestMsgEditWindowPrivate *priv;
3532 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3537 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3540 ModestMsgEditWindowPrivate *priv;
3542 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3547 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3548 ModestMsgEditWindow *window)
3550 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3554 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3557 ModestMsgEditWindowPrivate *priv;
3558 TnyHeader *header = NULL;
3560 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3561 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3563 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3564 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3566 if (priv->draft_msg != NULL) {
3567 g_object_unref (priv->draft_msg);
3570 if (draft != NULL) {
3571 g_object_ref (draft);
3572 header = tny_msg_get_header (draft);
3573 if (priv->msg_uid) {
3574 g_free (priv->msg_uid);
3575 priv->msg_uid = NULL;
3577 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3578 if (GTK_WIDGET_REALIZED (window)) {
3579 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3580 gtk_widget_destroy (GTK_WIDGET (window));
3586 priv->draft_msg = draft;
3590 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3591 GtkTextIter *start, GtkTextIter *end,
3594 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3595 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3598 if (tag == NULL) return;
3599 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3600 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3601 replace_with_images (window, priv->images);
3606 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3609 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3611 g_return_if_fail (TNY_IS_MIME_PART (part));
3612 tny_list_prepend (priv->attachments, (GObject *) part);
3613 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3614 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3615 gtk_widget_show_all (priv->attachments_caption);
3616 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3620 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3622 ModestMsgEditWindowPrivate *priv;
3624 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3625 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3627 return priv->msg_uid;
3631 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3632 ModestMsgEditWindowWidgetType widget_type)
3634 ModestMsgEditWindowPrivate *priv;
3636 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3637 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3639 switch (widget_type) {
3640 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3641 return priv->msg_body;
3643 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3644 return priv->to_field;
3646 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3647 return priv->cc_field;
3649 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3650 return priv->bcc_field;
3652 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3653 return priv->subject_field;
3655 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3656 return priv->attachments_view;
3664 remove_tags (WPTextBuffer *buffer)
3666 GtkTextIter start, end;
3668 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3669 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3671 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3675 on_account_removed (TnyAccountStore *account_store,
3676 TnyAccount *account,
3679 /* Do nothing if it's a store account, because we use the
3680 transport to send the messages */
3681 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3682 const gchar *parent_acc = NULL;
3683 const gchar *our_acc = NULL;
3685 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3686 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3687 /* Close this window if I'm showing a message of the removed account */
3688 if (strcmp (parent_acc, our_acc) == 0)
3689 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3694 from_field_changed (HildonPickerButton *button,
3695 ModestMsgEditWindow *self)
3697 ModestMsgEditWindowPrivate *priv;
3698 gboolean has_old_signature, has_new_signature;
3700 GtkTextIter match_start, match_end;
3701 ModestAccountMgr *mgr;
3703 gchar *full_signature;
3705 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3707 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3708 mgr = modest_runtime_get_account_mgr ();
3709 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3710 if (has_old_signature) {
3711 full_signature = g_strconcat ("\n--\n", signature, NULL);
3712 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3713 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3715 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3716 &match_start, &match_end, NULL)) {
3719 g_free (full_signature);
3723 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3724 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3725 if (has_new_signature) {
3726 full_signature = g_strconcat ("\n--\n", signature, NULL);
3727 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3728 g_free (full_signature);
3733 typedef struct _MessageSettingsHelper {
3734 ModestMsgEditWindow *window;
3735 GSList *priority_group;
3736 GSList *format_group;
3737 GtkToggleButton *current_priority;
3738 GtkToggleButton *current_format;
3739 } MessageSettingsHelper;
3742 on_priority_toggle (GtkToggleButton *button,
3743 MessageSettingsHelper *helper)
3746 ModestMsgEditWindowPrivate *priv;
3748 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3749 if (gtk_toggle_button_get_active (button)) {
3751 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3752 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3753 if ((node_button != button) &&
3754 gtk_toggle_button_get_active (node_button)) {
3755 gtk_toggle_button_set_active (node_button, FALSE);
3758 helper->current_priority = button;
3760 gboolean found = FALSE;
3761 /* If no one is active, activate it again */
3762 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3763 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3764 if (gtk_toggle_button_get_active (node_button)) {
3770 gtk_toggle_button_set_active (button, TRUE);
3776 on_format_toggle (GtkToggleButton *button,
3777 MessageSettingsHelper *helper)
3780 ModestMsgEditWindowPrivate *priv;
3782 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3783 if (gtk_toggle_button_get_active (button)) {
3785 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3786 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3787 if ((node_button != button) &&
3788 gtk_toggle_button_get_active (node_button)) {
3789 gtk_toggle_button_set_active (node_button, FALSE);
3792 helper->current_format = button;
3794 gboolean found = FALSE;
3795 /* If no one is active, activate it again */
3796 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3797 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3798 if (gtk_toggle_button_get_active (node_button)) {
3804 gtk_toggle_button_set_active (button, TRUE);
3811 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3816 GtkWidget *priority_hbox;
3817 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3818 GtkWidget *captioned;
3819 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3820 GtkWidget *format_hbox;
3821 GtkWidget *html_toggle, *text_toggle;
3822 ModestMsgEditWindowPrivate *priv;
3823 MessageSettingsHelper helper = {0,};
3825 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3826 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3827 helper.window = window;
3828 helper.priority_group = NULL;
3829 helper.format_group = NULL;
3831 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3832 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3834 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3835 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3836 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3837 vbox = gtk_vbox_new (FALSE, 0);
3838 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
3839 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
3840 gtk_container_add (GTK_CONTAINER (align), vbox);
3841 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
3842 gtk_widget_show (align);
3843 gtk_widget_show (vbox);
3845 /* Priority toggles */
3846 priority_hbox = gtk_hbox_new (TRUE, 0);
3847 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3848 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3849 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3850 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3851 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3852 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3853 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3854 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3855 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3856 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3857 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3858 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3859 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3860 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3861 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3862 gtk_widget_show_all (priority_hbox);
3863 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3864 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3865 gtk_widget_show (captioned);
3866 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3868 /* format toggles */
3869 format_hbox = gtk_hbox_new (TRUE, 0);
3870 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3871 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3872 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3873 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3874 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3875 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3876 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3877 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3878 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3879 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3880 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3881 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3882 gtk_widget_show_all (format_hbox);
3883 gtk_widget_show (format_hbox);
3884 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3887 g_object_unref (title_sizegroup);
3888 g_object_unref (value_sizegroup);
3890 /* Set current values */
3891 switch (priv->priority_flags) {
3892 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3893 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3894 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3896 case TNY_HEADER_FLAG_LOW_PRIORITY:
3897 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3898 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3901 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3902 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3906 switch (modest_msg_edit_window_get_format (window)) {
3907 case MODEST_MSG_EDIT_FORMAT_TEXT:
3908 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3909 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3911 case MODEST_MSG_EDIT_FORMAT_HTML:
3913 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3914 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3918 /* Signal connects */
3919 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3920 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3921 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3922 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3923 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3925 /* Save settings if the user clicked on done */
3926 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3927 TnyHeaderFlags flags;
3928 ModestMsgEditFormat old_format, new_format;
3930 /* Set priority flags */
3931 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3932 if (priv->priority_flags != flags)
3933 modest_msg_edit_window_set_priority_flags (window, flags);
3935 /* Set edit format */
3936 old_format = modest_msg_edit_window_get_format (window);
3937 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3938 if (old_format != new_format) {
3939 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3940 modest_msg_edit_window_set_file_format (window, file_format);
3944 gtk_widget_destroy (dialog);
3945 g_slist_free (helper.priority_group);
3949 on_message_settings (GtkAction *action,
3950 ModestMsgEditWindow *window)
3952 modest_msg_edit_window_show_msg_settings_dialog (window);
3956 on_cc_button_toggled (HildonCheckButton *button,
3957 ModestMsgEditWindow *window)
3959 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3961 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3962 hildon_check_button_get_active (button));
3966 on_bcc_button_toggled (HildonCheckButton *button,
3967 ModestMsgEditWindow *window)
3969 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3971 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3972 hildon_check_button_get_active (button));
3976 setup_menu (ModestMsgEditWindow *self)
3978 ModestMsgEditWindowPrivate *priv = NULL;
3980 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3982 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3984 /* Settings menu buttons */
3985 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3986 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3988 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3989 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3990 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3992 priv->cc_button = hildon_check_button_new (0);
3993 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3994 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3996 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3998 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3999 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4000 priv->bcc_button = hildon_check_button_new (0);
4001 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4002 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4004 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4006 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4007 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4009 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4010 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4011 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4012 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4013 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4014 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4015 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4016 APP_MENU_CALLBACK (on_message_settings),
4018 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4019 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),