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