1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
42 #include <modest-account-mgr.h>
43 #include <modest-account-mgr-helpers.h>
45 #include <widgets/modest-msg-edit-window.h>
46 #include <modest-selector-picker.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <modest-wp-text-view.h>
65 #include <wptextbuffer.h>
66 #include <hildon/hildon-pannable-area.h>
67 #include <hildon/hildon-touch-selector.h>
68 #include <hildon/hildon-picker-dialog.h>
69 #include "modest-msg-edit-window-ui-dimming.h"
71 #include "modest-hildon-includes.h"
72 #ifdef MODEST_HAVE_HILDON0_WIDGETS
73 #include <hildon-widgets/hildon-color-chooser.h>
75 #include "widgets/modest-msg-edit-window-ui.h"
76 #ifdef MODEST_HAVE_HILDON0_WIDGETS
77 #include <libgnomevfs/gnome-vfs-mime-utils.h>
79 #include <libgnomevfs/gnome-vfs-mime.h>
81 #include <modest-utils.h>
82 #include "modest-maemo-utils.h"
83 #include <modest-ui-constants.h>
86 #define DEFAULT_FONT_SIZE 3
87 #define DEFAULT_FONT 2
88 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
89 #define DEFAULT_MAIN_VBOX_SPACING 6
90 #define SUBJECT_MAX_LENGTH 1000
91 #define IMAGE_MAX_WIDTH 560
92 #define DEFAULT_FONT_SCALE 1.5
93 #define ATTACHMENT_BUTTON_WIDTH 118
95 static gboolean is_wp_text_buffer_started = FALSE;
97 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
98 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
99 static void modest_msg_edit_window_finalize (GObject *obj);
101 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
102 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
103 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
105 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
106 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
107 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
108 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
109 GtkTextIter *start, GtkTextIter *end,
111 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
112 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
113 static void subject_field_insert_text (GtkEditable *editable,
115 gint new_text_length,
117 ModestMsgEditWindow *window);
118 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
120 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
122 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
123 ModestRecptEditor *editor);
124 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
125 ModestMsgEditWindow *window);
127 /* ModestWindow methods implementation */
128 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
129 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
130 gboolean show_toolbar);
131 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
133 ModestMsgEditWindow *window);
134 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
135 static void subject_field_move_cursor (GtkEntry *entry,
136 GtkMovementStep step,
140 static void update_window_title (ModestMsgEditWindow *window);
143 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
144 ModestMsgEditWindow *window);
145 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
146 ModestMsgEditWindow *window);
147 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
149 GtkTextIter *match_start,
150 GtkTextIter *match_end);
152 static void remove_tags (WPTextBuffer *buffer);
154 static void on_account_removed (TnyAccountStore *account_store,
158 static void init_window (ModestMsgEditWindow *obj);
160 gboolean scroll_drag_timeout (gpointer userdata);
161 static void correct_scroll (ModestMsgEditWindow *w);
162 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
163 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
164 ModestMsgEditWindow *userdata);
165 static void text_buffer_mark_set (GtkTextBuffer *buffer,
168 ModestMsgEditWindow *userdata);
169 static void on_message_settings (GtkAction *action,
170 ModestMsgEditWindow *window);
171 static void setup_menu (ModestMsgEditWindow *self);
173 static void from_field_changed (HildonPickerButton *button,
174 ModestMsgEditWindow *self);
175 static void font_size_clicked (GtkToolButton *button,
176 ModestMsgEditWindow *window);
177 static void font_face_clicked (GtkToolButton *button,
178 ModestMsgEditWindow *window);
179 static void DEBUG_BUFFER (WPTextBuffer *buffer)
183 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
185 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
186 while (!gtk_text_iter_is_end (&iter)) {
187 GString *output = g_string_new ("");
188 GSList *toggled_tags;
191 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
192 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
193 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
194 GtkTextTag *tag = (GtkTextTag *) node->data;
196 g_object_get (G_OBJECT (tag), "name", &name, NULL);
197 output = g_string_append (output, name);
198 g_string_append (output, " ");
200 output = g_string_append (output, "] OPENED [ ");
201 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
202 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
203 GtkTextTag *tag = (GtkTextTag *) node->data;
205 g_object_get (G_OBJECT (tag), "name", &name, NULL);
206 output = g_string_append (output, name);
207 g_string_append (output, " ");
209 output = g_string_append (output, "]\n");
210 g_message ("%s", output->str);
211 g_string_free (output, TRUE);
212 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
214 g_message ("END BUFFER");
218 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
219 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
223 /* static gboolean */
224 /* on_key_pressed (GtkWidget *self, */
225 /* GdkEventKey *event, */
226 /* gpointer user_data); */
228 /* list my signals */
235 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
236 struct _ModestMsgEditWindowPrivate {
238 GtkWidget *header_box;
240 ModestPairList *from_field_protos;
241 GtkWidget *from_field;
242 gchar *last_from_account;
243 gchar *original_account_name;
247 GtkWidget *bcc_field;
248 GtkWidget *subject_field;
249 GtkWidget *attachments_view;
250 GtkWidget *priority_icon;
251 GtkWidget *subject_box;
252 GtkWidget *add_attachment_button;
254 GtkWidget *cc_caption;
255 GtkWidget *bcc_caption;
256 gboolean update_caption_visibility;
257 GtkWidget *attachments_caption;
259 GtkTextBuffer *text_buffer;
261 GtkWidget *font_size_toolitem;
262 GtkWidget *font_face_toolitem;
263 GtkWidget *font_color_button;
264 GtkWidget *font_color_toolitem;
265 GSList *font_items_group;
266 GtkTreeModel *faces_model;
267 gint current_face_index;
268 GtkWidget *font_tool_button_label;
269 GtkTreeModel *sizes_model;
270 gint current_size_index;
271 GtkWidget *size_tool_button_label;
273 GtkWidget *find_toolbar;
276 GtkWidget *font_dialog;
279 guint correct_scroll_idle;
280 guint scroll_drag_timeout_id;
284 TnyList *attachments;
289 TnyHeaderFlags priority_flags;
291 gboolean can_undo, can_redo;
292 gulong clipboard_change_handler_id;
293 gulong default_clipboard_change_handler_id;
294 gulong account_removed_handler_id;
295 guint clipboard_owner_idle;
296 gchar *clipboard_text;
305 GtkWidget *cc_button;
306 GtkWidget *bcc_button;
309 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
310 MODEST_TYPE_MSG_EDIT_WINDOW, \
311 ModestMsgEditWindowPrivate))
313 static GtkWindowClass *parent_class = NULL;
315 /* uncomment the following if you have defined any signals */
316 /* static guint signals[LAST_SIGNAL] = {0}; */
319 modest_msg_edit_window_get_type (void)
321 static GType my_type = 0;
323 static const GTypeInfo my_info = {
324 sizeof(ModestMsgEditWindowClass),
325 NULL, /* base init */
326 NULL, /* base finalize */
327 (GClassInitFunc) modest_msg_edit_window_class_init,
328 NULL, /* class finalize */
329 NULL, /* class data */
330 sizeof(ModestMsgEditWindow),
332 (GInstanceInitFunc) modest_msg_edit_window_init,
335 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
336 "ModestMsgEditWindow",
344 save_state (ModestWindow *self)
346 modest_widget_memory_save (modest_runtime_get_conf(),
347 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
352 restore_settings (ModestMsgEditWindow *self)
354 ModestConf *conf = NULL;
356 conf = modest_runtime_get_conf ();
358 /* Dim at start clipboard actions */
359 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
364 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
366 GObjectClass *gobject_class;
367 ModestWindowClass *modest_window_class;
368 gobject_class = (GObjectClass*) klass;
369 modest_window_class = (ModestWindowClass*) klass;
371 parent_class = g_type_class_peek_parent (klass);
372 gobject_class->finalize = modest_msg_edit_window_finalize;
374 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
375 modest_window_class->save_state_func = save_state;
376 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
378 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
382 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
384 ModestMsgEditWindowPrivate *priv;
385 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
387 priv->msg_body = NULL;
388 priv->from_field = NULL;
389 priv->to_field = NULL;
390 priv->cc_field = NULL;
391 priv->bcc_field = NULL;
392 priv->subject_field = NULL;
393 priv->attachments = TNY_LIST (tny_simple_list_new ());
394 priv->images = TNY_LIST (tny_simple_list_new ());
395 priv->images_size = 0;
396 priv->images_count = 0;
399 priv->cc_caption = NULL;
400 priv->bcc_caption = NULL;
401 priv->update_caption_visibility = FALSE;
403 priv->priority_flags = 0;
405 priv->find_toolbar = NULL;
406 priv->last_search = NULL;
408 priv->draft_msg = NULL;
409 priv->outbox_msg = NULL;
410 priv->msg_uid = NULL;
412 priv->can_undo = FALSE;
413 priv->can_redo = FALSE;
414 priv->clipboard_change_handler_id = 0;
415 priv->default_clipboard_change_handler_id = 0;
416 priv->account_removed_handler_id = 0;
417 priv->clipboard_owner_idle = 0;
418 priv->clipboard_text = NULL;
421 priv->scroll_drag_timeout_id = 0;
422 priv->correct_scroll_idle = 0;
423 priv->last_upper = 0.0;
425 priv->font_dialog = NULL;
426 priv->app_menu = NULL;
428 if (!is_wp_text_buffer_started) {
429 is_wp_text_buffer_started = TRUE;
430 wp_text_buffer_library_init ();
435 hildon_program_add_window (hildon_program_get_instance(),
441 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
443 static ModestPairList*
444 get_transports (void)
446 GSList *transports = NULL;
448 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
449 GSList *accounts = modest_account_mgr_account_names (account_mgr,
450 TRUE /* only enabled accounts. */);
452 GSList *cursor = accounts;
454 gchar *account_name = cursor->data;
455 gchar *from_string = NULL;
457 from_string = modest_account_mgr_get_from_string (account_mgr,
461 if (from_string && account_name) {
462 gchar *name = account_name;
463 ModestPair *pair = modest_pair_new ((gpointer) name,
464 (gpointer) from_string , TRUE);
465 transports = g_slist_prepend (transports, pair);
468 cursor = cursor->next;
470 g_slist_free (accounts); /* only free the accounts, not the elements,
471 * because they are used in the pairlist */
475 static void window_focus (GtkWindow *window,
479 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
483 scroll_drag_timeout (gpointer userdata)
485 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
486 ModestMsgEditWindowPrivate *priv;
488 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
490 correct_scroll_without_drag_check (win, TRUE);
492 priv->scroll_drag_timeout_id = 0;
498 correct_scroll_without_drag_check_idle (gpointer userdata)
500 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
501 ModestMsgEditWindowPrivate *priv;
503 GdkRectangle rectangle;
504 gint offset_min, offset_max;
508 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
510 insert = gtk_text_buffer_get_insert (priv->text_buffer);
511 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
513 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
514 offset_min = priv->msg_body->allocation.y + rectangle.y;
515 offset_max = offset_min + rectangle.height;
517 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
518 offset_min = MAX (offset_min - 48, 0);
519 offset_max = MIN (offset_max + 48, vadj->upper);
521 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
523 priv->correct_scroll_idle = 0;
528 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
530 ModestMsgEditWindowPrivate *priv;
532 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
534 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
537 if (priv->correct_scroll_idle > 0) {
541 priv->correct_scroll_idle = g_idle_add ((GSourceFunc) correct_scroll_without_drag_check_idle,
546 correct_scroll (ModestMsgEditWindow *w)
548 ModestMsgEditWindowPrivate *priv;
550 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
551 if (gtk_grab_get_current () == priv->msg_body) {
552 if (priv->scroll_drag_timeout_id == 0) {
553 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
559 correct_scroll_without_drag_check (w, TRUE);
563 text_buffer_end_user_action (GtkTextBuffer *buffer,
564 ModestMsgEditWindow *userdata)
567 correct_scroll (userdata);
571 text_buffer_mark_set (GtkTextBuffer *buffer,
574 ModestMsgEditWindow *userdata)
576 gtk_text_buffer_begin_user_action (buffer);
577 gtk_text_buffer_end_user_action (buffer);
581 cut_clipboard_check (GtkTextView *text_view,
584 GtkTextBuffer *buffer;
586 buffer = gtk_text_view_get_buffer (text_view);
587 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
588 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
593 copy_clipboard_check (GtkTextView *text_view,
596 GtkTextBuffer *buffer;
598 buffer = gtk_text_view_get_buffer (text_view);
599 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
600 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
605 attachment_deleted (ModestAttachmentsView *attachments_view,
608 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
613 connect_signals (ModestMsgEditWindow *obj)
615 ModestMsgEditWindowPrivate *priv;
617 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
619 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
620 G_CALLBACK (text_buffer_refresh_attributes), obj);
621 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
622 G_CALLBACK (text_buffer_can_undo), obj);
623 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
624 G_CALLBACK (text_buffer_can_redo), obj);
625 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
626 G_CALLBACK (body_changed), obj);
627 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
628 G_CALLBACK (body_changed), obj);
629 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
630 G_CALLBACK (text_buffer_end_user_action), obj);
631 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
632 G_CALLBACK (text_buffer_mark_set), obj);
633 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
634 G_CALLBACK (text_buffer_apply_tag), obj);
635 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
636 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
637 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
638 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
639 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
640 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
642 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
643 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
644 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
645 G_CALLBACK (from_field_changed), obj);
647 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
648 G_CALLBACK (msg_body_focus), obj);
649 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
650 G_CALLBACK (msg_body_focus), obj);
651 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
652 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
653 "changed", G_CALLBACK (recpt_field_changed), obj);
654 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
655 "changed", G_CALLBACK (recpt_field_changed), obj);
656 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
657 "changed", G_CALLBACK (recpt_field_changed), obj);
658 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
659 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
660 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
662 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
663 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
665 priv->clipboard_change_handler_id =
666 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
667 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
668 priv->default_clipboard_change_handler_id =
669 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
670 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
672 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
673 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
674 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
678 init_wp_text_view_style ()
680 static gboolean initialized = FALSE;
683 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
689 init_window (ModestMsgEditWindow *obj)
691 GtkWidget *to_caption, *subject_caption;
692 GtkWidget *main_vbox;
693 GtkWidget *add_attachment_align;
694 ModestMsgEditWindowPrivate *priv;
695 GtkActionGroup *action_group;
696 ModestWindowPrivate *parent_priv;
697 GdkPixbuf *window_icon = NULL;
698 GError *error = NULL;
700 GtkSizeGroup *title_size_group;
701 GtkSizeGroup *value_size_group;
702 GtkWidget *attachment_icon;
703 GtkWidget *window_box;
704 GtkWidget *window_align;
705 #if (GTK_MINOR_VERSION >= 10)
706 GdkAtom deserialize_type;
709 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
710 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
712 parent_priv->ui_manager = gtk_ui_manager_new();
713 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
714 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
716 /* Add common actions */
717 gtk_action_group_add_actions (action_group,
718 modest_msg_edit_action_entries,
719 G_N_ELEMENTS (modest_msg_edit_action_entries),
721 gtk_action_group_add_actions (action_group,
722 hildon2_msg_edit_action_entries,
723 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
725 gtk_action_group_add_toggle_actions (action_group,
726 modest_msg_edit_toggle_action_entries,
727 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
729 gtk_action_group_add_radio_actions (action_group,
730 modest_msg_edit_alignment_radio_action_entries,
731 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
733 G_CALLBACK (modest_ui_actions_on_change_justify),
735 gtk_action_group_add_radio_actions (action_group,
736 modest_msg_edit_priority_action_entries,
737 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
739 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
741 gtk_action_group_add_radio_actions (action_group,
742 modest_msg_edit_file_format_action_entries,
743 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
744 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
745 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
747 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
748 g_object_unref (action_group);
750 /* Load the UI definition */
751 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
754 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
755 g_clear_error (&error);
758 /* Add accelerators */
759 gtk_window_add_accel_group (GTK_WINDOW (obj),
760 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
762 parent_priv->menubar = NULL;
764 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
765 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
767 /* Note: This ModestPairList* must exist for as long as the picker
768 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
769 * so it can't know how to manage its memory. */
770 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
771 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
773 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
774 _("mail_va_from"), priv->from_field);
776 priv->to_field = modest_recpt_editor_new ();
777 priv->cc_field = modest_recpt_editor_new ();
778 priv->bcc_field = modest_recpt_editor_new ();
779 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
780 priv->priority_icon = gtk_image_new ();
781 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
782 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
783 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
784 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
785 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
786 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
787 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
788 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
789 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
790 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
791 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
792 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
793 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
794 add_attachment_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
795 gtk_alignment_set_padding (GTK_ALIGNMENT (add_attachment_align), 0, 0, MODEST_MARGIN_DEFAULT, 0);
796 gtk_container_add (GTK_CONTAINER (add_attachment_align), priv->add_attachment_button);
797 gtk_box_pack_start (GTK_BOX (priv->subject_box), add_attachment_align, FALSE, FALSE, 0);
798 priv->attachments_view = modest_attachments_view_new (NULL);
799 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
800 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
802 priv->header_box = gtk_vbox_new (FALSE, 0);
804 to_caption = modest_maemo_utils_create_captioned_with_size_type
805 (title_size_group, value_size_group,
806 _("mail_va_to"), FALSE, priv->to_field,
807 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
808 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
809 (title_size_group, value_size_group,
810 _("mail_va_cc"), FALSE, priv->cc_field,
811 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
812 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
813 (title_size_group, value_size_group,
814 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
815 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
816 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
817 _("mail_va_subject"), FALSE, priv->subject_box);
818 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
819 _("mail_va_attachment"),
821 priv->attachments_view,
822 HILDON_SIZE_AUTO_WIDTH |
823 HILDON_SIZE_AUTO_HEIGHT);
824 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
825 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
826 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
827 g_object_unref (title_size_group);
828 g_object_unref (value_size_group);
830 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
831 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
832 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
833 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
834 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
835 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
836 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
838 init_wp_text_view_style ();
840 priv->msg_body = modest_wp_text_view_new ();
843 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
844 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
845 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
846 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
847 #if (GTK_MINOR_VERSION >= 10)
848 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
849 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
851 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
852 deserialize_type, TRUE);
854 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
856 priv->find_toolbar = hildon_find_toolbar_new (NULL);
857 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
859 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
861 priv->pannable = hildon_pannable_area_new ();
863 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
864 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
865 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
867 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
868 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
869 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
871 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
872 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox),
873 hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable)));
874 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
876 window_box = gtk_vbox_new (FALSE, 0);
877 gtk_container_add (GTK_CONTAINER(obj), window_box);
879 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
881 /* Set window icon */
882 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
884 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
885 g_object_unref (window_icon);
890 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
892 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
894 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
895 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
896 priv->clipboard_change_handler_id))
897 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
898 priv->clipboard_change_handler_id);
899 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
900 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
901 priv->default_clipboard_change_handler_id))
902 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
903 priv->default_clipboard_change_handler_id);
905 if (priv->account_removed_handler_id &&
906 g_signal_handler_is_connected (modest_runtime_get_account_store (),
907 priv->account_removed_handler_id))
908 g_signal_handler_disconnect(modest_runtime_get_account_store (),
909 priv->account_removed_handler_id);
913 modest_msg_edit_window_finalize (GObject *obj)
915 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
917 /* Sanity check: shouldn't be needed, the window mgr should
918 call this function before */
919 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
921 if (priv->font_dialog != NULL) {
922 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
925 if (priv->clipboard_text != NULL) {
926 g_free (priv->clipboard_text);
927 priv->clipboard_text = NULL;
930 if (priv->draft_msg != NULL) {
931 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
932 if (TNY_IS_HEADER (header)) {
933 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
934 modest_window_mgr_unregister_header (mgr, header);
936 g_object_unref (priv->draft_msg);
937 priv->draft_msg = NULL;
939 if (priv->outbox_msg != NULL) {
940 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
941 if (TNY_IS_HEADER (header)) {
942 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
943 modest_window_mgr_unregister_header (mgr, header);
945 g_object_unref (priv->outbox_msg);
946 priv->outbox_msg = NULL;
948 if (priv->correct_scroll_idle > 0) {
949 g_source_remove (priv->correct_scroll_idle);
950 priv->correct_scroll_idle = 0;
952 if (priv->scroll_drag_timeout_id > 0) {
953 g_source_remove (priv->scroll_drag_timeout_id);
954 priv->scroll_drag_timeout_id = 0;
956 if (priv->clipboard_owner_idle > 0) {
957 g_source_remove (priv->clipboard_owner_idle);
958 priv->clipboard_owner_idle = 0;
960 if (priv->original_account_name)
961 g_free (priv->original_account_name);
962 g_free (priv->msg_uid);
963 g_free (priv->last_search);
964 g_object_unref (priv->faces_model);
965 g_object_unref (priv->sizes_model);
966 g_object_unref (priv->attachments);
967 g_object_unref (priv->images);
969 /* This had to stay alive for as long as the picker that used it: */
970 modest_pair_list_free (priv->from_field_protos);
972 G_OBJECT_CLASS(parent_class)->finalize (obj);
976 pixbuf_from_stream (TnyStream *stream,
977 const gchar *mime_type,
978 guint64 *stream_size,
979 ModestMsgEditWindow *self)
981 GdkPixbufLoader *loader;
984 GError *error = NULL;
988 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
990 if (loader == NULL) {
996 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
998 tny_stream_reset (TNY_STREAM (stream));
999 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1000 unsigned char read_buffer[128];
1002 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1004 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1007 /* Allow some UI responsiveness */
1008 while (gtk_events_pending ())
1009 gtk_main_iteration ();
1011 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1013 gdk_pixbuf_loader_close (loader, &error);
1016 g_error_free (error);
1017 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1019 g_object_ref (pixbuf);
1020 g_object_unref (loader);
1025 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1026 GdkPixbuf *new_pixbuf;
1028 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1029 gdk_pixbuf_get_width (pixbuf);
1030 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1031 g_object_unref (pixbuf);
1032 pixbuf = new_pixbuf;
1036 *stream_size = size;
1042 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1044 ModestMsgEditWindowPrivate *priv;
1047 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1049 g_object_ref (self);
1050 for (iter = tny_list_create_iterator (attachments);
1051 !tny_iterator_is_done (iter);
1052 tny_iterator_next (iter)) {
1053 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1054 const gchar *cid = tny_mime_part_get_content_id (part);
1055 const gchar *mime_type = tny_mime_part_get_content_type (part);
1056 if ((cid != NULL)&&(mime_type != NULL)) {
1057 guint64 stream_size;
1058 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1059 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1062 g_object_unref (stream);
1064 if (pixbuf != NULL) {
1065 priv->images_count ++;
1066 priv->images_size += stream_size;
1067 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1068 g_object_unref (pixbuf);
1071 g_object_unref (part);
1073 g_object_unref (iter);
1074 g_object_unref (self);
1078 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1080 TnyMimePart *parent = NULL;
1081 const gchar *content_type = NULL;
1082 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1084 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1086 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1087 parent = g_object_ref (msg);
1088 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1089 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1092 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1093 iter = tny_list_create_iterator (parts);
1094 while (!tny_iterator_is_done (iter)) {
1096 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1097 content_type = tny_mime_part_get_content_type (part);
1098 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1102 g_object_unref (part);
1104 tny_iterator_next (iter);
1106 g_object_unref (iter);
1107 g_object_unref (parts);
1110 if (parent != NULL) {
1111 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1114 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1115 iter = tny_list_create_iterator (parts);
1116 while (!tny_iterator_is_done (iter)) {
1118 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1119 content_type = tny_mime_part_get_content_type (part);
1120 if (content_type && g_str_has_prefix (content_type, "image/")) {
1121 tny_list_prepend (priv->images, (GObject *) part);
1123 g_object_unref (part);
1124 tny_iterator_next (iter);
1126 g_object_unref (iter);
1127 g_object_unref (parts);
1128 g_object_unref (parent);
1133 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1136 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1138 for (iter = tny_list_create_iterator (attachments) ;
1139 !tny_iterator_is_done (iter);
1140 tny_iterator_next (iter)) {
1141 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1142 const gchar *cid = tny_mime_part_get_content_id (part);
1144 char *invalid = NULL;
1145 gint int_cid = strtol (cid, &invalid, 10);
1146 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1147 priv->next_cid = int_cid + 1;
1150 g_object_unref (part);
1152 g_object_unref (iter);
1156 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1159 gchar *to, *cc, *bcc, *subject;
1161 ModestMsgEditWindowPrivate *priv;
1162 ModestWindowPrivate *parent_priv;
1164 TnyHeaderFlags priority_flags;
1165 TnyFolder *msg_folder;
1166 gboolean is_html = FALSE;
1167 gboolean field_view_set;
1169 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1170 g_return_if_fail (TNY_IS_MSG (msg));
1172 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1173 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1175 header = tny_msg_get_header (msg);
1176 to = tny_header_dup_to (header);
1177 cc = tny_header_dup_cc (header);
1178 bcc = tny_header_dup_bcc (header);
1179 subject = tny_header_dup_subject (header);
1180 priority_flags = tny_header_get_priority (header);
1183 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1185 field_view_set = TRUE;
1187 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1188 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1189 gtk_widget_show (priv->cc_caption);
1190 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1191 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1192 gtk_widget_hide (priv->cc_caption);
1193 field_view_set = FALSE;
1195 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1197 field_view_set = TRUE;
1199 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1200 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1201 gtk_widget_show (priv->bcc_caption);
1202 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1203 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1204 gtk_widget_hide (priv->bcc_caption);
1205 field_view_set = FALSE;
1207 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1211 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1212 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1215 update_window_title (self);
1217 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1218 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1220 if ((body == NULL)||(body[0] == '\0')) {
1222 body = modest_text_utils_convert_to_html ("");
1225 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1226 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1229 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1232 /* Add attachments to the view */
1233 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1234 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1235 if (tny_list_get_length (priv->attachments) == 0) {
1236 gtk_widget_hide (priv->attachments_caption);
1238 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1239 gtk_widget_show_all (priv->attachments_caption);
1241 get_related_images (self, msg);
1242 update_next_cid (self, priv->attachments);
1243 update_next_cid (self, priv->images);
1244 replace_with_images (self, priv->images);
1246 if (preserve_is_rich && !is_html) {
1247 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1248 /* Get the default format required from configuration */
1249 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1250 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1253 /* Set the default focus depending on having already a To: field or not */
1254 if ((!to)||(*to == '\0')) {
1255 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1257 gtk_widget_grab_focus (priv->msg_body);
1260 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1262 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1263 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1265 modest_msg_edit_window_set_modified (self, FALSE);
1267 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1268 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1269 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1270 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1272 if (priv->msg_uid) {
1273 g_free (priv->msg_uid);
1274 priv->msg_uid = NULL;
1277 /* we should set a reference to the incoming message if it is a draft */
1278 msg_folder = tny_msg_get_folder (msg);
1280 if (modest_tny_folder_is_local_folder (msg_folder)) {
1281 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1282 if (type == TNY_FOLDER_TYPE_INVALID)
1283 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1285 if (type == TNY_FOLDER_TYPE_DRAFTS)
1286 priv->draft_msg = g_object_ref(msg);
1287 if (type == TNY_FOLDER_TYPE_OUTBOX)
1288 priv->outbox_msg = g_object_ref(msg);
1289 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1291 g_object_unref (msg_folder);
1302 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1304 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1305 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1306 GtkWidget *placeholder;
1307 GtkWidget *tool_item;
1312 GtkWidget *sizes_menu;
1313 GtkWidget *fonts_menu;
1317 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1318 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1319 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1320 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1322 /* Font color placeholder */
1323 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1324 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1327 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1328 priv->font_color_button = hildon_color_button_new ();
1329 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1330 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1331 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1332 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1333 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1334 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1335 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1336 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1338 G_CALLBACK (modest_msg_edit_window_color_button_change),
1341 /* Font size and face placeholder */
1342 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1343 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1345 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1346 priv->size_tool_button_label = gtk_label_new (NULL);
1347 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1348 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1349 size_text, "</span>", NULL);
1350 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1352 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1353 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1354 sizes_menu = gtk_menu_new ();
1355 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1356 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1359 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1360 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1362 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1366 if (wp_font_size[size_index] == 12)
1367 priv->current_size_index = size_index;
1371 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1372 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1373 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1374 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1375 priv->font_size_toolitem = tool_item;
1378 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1379 priv->font_tool_button_label = gtk_label_new (NULL);
1380 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1381 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1383 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1384 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1385 fonts_menu = gtk_menu_new ();
1386 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1387 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1390 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1392 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1393 0, wp_get_font_name (font_index),
1396 if (font_index == DEFAULT_FONT)
1397 priv->current_face_index = font_index;
1399 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1400 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1401 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1402 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1403 priv->font_face_toolitem = tool_item;
1405 /* Set expand and homogeneous for remaining items */
1406 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1407 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1408 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1409 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1410 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1411 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1412 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1413 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1414 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1416 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1417 will not show the tool items added to the placeholders) */
1418 gtk_widget_show_all (parent_priv->toolbar);
1420 /* Set the no show all *after* showing all items. We do not
1421 want the toolbar to be shown with a show all because it
1422 could go agains the gconf setting regarding showing or not
1423 the toolbar of the editor window */
1424 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1430 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1433 ModestWindowPrivate *parent_priv;
1434 ModestMsgEditWindowPrivate *priv;
1435 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1436 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1437 ModestWindowMgr *mgr = NULL;
1439 g_return_val_if_fail (msg, NULL);
1440 g_return_val_if_fail (account_name, NULL);
1442 mgr = modest_runtime_get_window_mgr ();
1444 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1446 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1447 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1449 /* Menubar. Update the state of some toggles */
1450 priv->from_field_protos = get_transports ();
1451 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1452 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1453 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1454 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1456 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1457 hildon_touch_selector_get_current_text
1458 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1459 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1460 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1463 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1465 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1467 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1469 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1471 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1472 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1473 /* Add common dimming rules */
1474 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1475 modest_msg_edit_window_toolbar_dimming_entries,
1476 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1477 MODEST_WINDOW (obj));
1478 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1479 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1480 MODEST_WINDOW (obj));
1481 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1482 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1483 MODEST_WINDOW (obj));
1484 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1485 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1486 MODEST_WINDOW (obj));
1487 /* Insert dimming rules group for this window */
1488 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1489 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1491 /* Setup app menu */
1492 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1494 /* Checks the dimming rules */
1495 g_object_unref (toolbar_rules_group);
1496 g_object_unref (clipboard_rules_group);
1497 gtk_widget_hide (priv->priority_icon);
1498 gtk_widget_queue_resize (priv->subject_box);
1499 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1501 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1503 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1504 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1505 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1506 priv->update_caption_visibility = TRUE;
1508 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1510 /* Track account-removed signal, this window should be closed
1511 in the case we're creating a mail associated to the account
1513 priv->account_removed_handler_id =
1514 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1516 G_CALLBACK(on_account_removed),
1519 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1521 return (ModestWindow*) obj;
1525 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1527 GString **string_buffer = (GString **) user_data;
1529 *string_buffer = g_string_append (*string_buffer, buffer);
1535 * @result: A new string which should be freed with g_free().
1538 get_formatted_data (ModestMsgEditWindow *edit_window)
1540 ModestMsgEditWindowPrivate *priv;
1541 GString *string_buffer = g_string_new ("");
1543 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1545 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1547 modest_text_utils_hyperlinkify (string_buffer);
1549 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1551 return g_string_free (string_buffer, FALSE);
1556 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1559 const gchar *account_name;
1560 ModestMsgEditWindowPrivate *priv;
1561 TnyIterator *att_iter;
1563 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1565 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1567 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1568 g_return_val_if_fail (account_name, NULL);
1571 /* don't free these (except from) */
1572 data = g_slice_new0 (MsgData);
1573 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1575 data->account_name = g_strdup (account_name);
1576 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1577 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1578 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1579 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1580 if (priv->draft_msg) {
1581 data->draft_msg = g_object_ref (priv->draft_msg);
1582 } else if (priv->outbox_msg) {
1583 data->draft_msg = g_object_ref (priv->outbox_msg);
1585 data->draft_msg = NULL;
1588 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1590 gtk_text_buffer_get_bounds (buf, &b, &e);
1591 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1593 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1594 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1596 data->html_body = NULL;
1598 /* deep-copy the data */
1599 att_iter = tny_list_create_iterator (priv->attachments);
1600 data->attachments = NULL;
1601 while (!tny_iterator_is_done (att_iter)) {
1602 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1603 if (!(TNY_IS_MIME_PART(part))) {
1604 g_warning ("strange data in attachment list");
1605 g_object_unref (part);
1606 tny_iterator_next (att_iter);
1609 data->attachments = g_list_append (data->attachments,
1611 tny_iterator_next (att_iter);
1613 g_object_unref (att_iter);
1615 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1616 att_iter = tny_list_create_iterator (priv->images);
1617 data->images = NULL;
1618 while (!tny_iterator_is_done (att_iter)) {
1619 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1621 if (!(TNY_IS_MIME_PART(part))) {
1622 g_warning ("strange data in attachment list");
1623 g_object_unref (part);
1624 tny_iterator_next (att_iter);
1627 cid = tny_mime_part_get_content_id (part);
1629 gchar *image_tag_id;
1630 GtkTextTag *image_tag;
1632 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1633 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1634 g_free (image_tag_id);
1636 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1638 ((gtk_text_iter_has_tag (&iter, image_tag))||
1639 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1640 data->images = g_list_append (data->images,
1641 g_object_ref (part));
1643 g_object_unref (part);
1644 tny_iterator_next (att_iter);
1646 g_object_unref (att_iter);
1648 data->priority_flags = priv->priority_flags;
1655 unref_gobject (GObject *obj, gpointer data)
1657 if (!G_IS_OBJECT(obj))
1659 g_object_unref (obj);
1663 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1666 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1674 g_free (data->from);
1675 g_free (data->subject);
1676 g_free (data->plain_body);
1677 g_free (data->html_body);
1678 g_free (data->account_name);
1680 if (data->draft_msg != NULL) {
1681 g_object_unref (data->draft_msg);
1682 data->draft_msg = NULL;
1685 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1686 g_list_free (data->attachments);
1687 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1688 g_list_free (data->images);
1690 g_slice_free (MsgData, data);
1694 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1696 guint64 *parts_size)
1698 ModestMsgEditWindowPrivate *priv;
1700 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1702 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1704 /* TODO: add images */
1705 *parts_size += priv->images_size;
1706 *parts_count += priv->images_count;
1711 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1714 ModestMsgEditWindowPrivate *priv = NULL;
1715 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1717 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1719 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1721 return MODEST_MSG_EDIT_FORMAT_HTML;
1723 return MODEST_MSG_EDIT_FORMAT_TEXT;
1727 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1728 ModestMsgEditFormat format)
1730 ModestMsgEditWindowPrivate *priv;
1732 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1733 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1736 case MODEST_MSG_EDIT_FORMAT_HTML:
1737 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1739 case MODEST_MSG_EDIT_FORMAT_TEXT:
1740 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1743 g_return_if_reached ();
1747 ModestMsgEditFormatState *
1748 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1750 ModestMsgEditFormatState *format_state = NULL;
1751 ModestMsgEditWindowPrivate *priv;
1752 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1754 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1755 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1757 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1759 format_state = g_new0 (ModestMsgEditFormatState, 1);
1760 format_state->bold = buffer_format->bold&0x1;
1761 format_state->italics = buffer_format->italic&0x1;
1762 format_state->bullet = buffer_format->bullet&0x1;
1763 format_state->color = buffer_format->color;
1764 format_state->font_size = buffer_format->font_size;
1765 format_state->font_family = wp_get_font_name (buffer_format->font);
1766 format_state->justification = buffer_format->justification;
1767 g_free (buffer_format);
1769 return format_state;
1774 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1775 const ModestMsgEditFormatState *format_state)
1777 ModestMsgEditWindowPrivate *priv;
1778 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1779 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1780 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1781 g_return_if_fail (format_state != NULL);
1783 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1784 gtk_widget_grab_focus (priv->msg_body);
1785 buffer_format->bold = (format_state->bold != FALSE);
1786 buffer_format->italic = (format_state->italics != FALSE);
1787 buffer_format->color = format_state->color;
1788 buffer_format->font_size = format_state->font_size;
1789 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1790 buffer_format->justification = format_state->justification;
1791 buffer_format->bullet = format_state->bullet;
1793 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1795 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1796 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1797 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1798 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1799 buffer_format->cs.font = (buffer_format->font != current_format->font);
1800 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1801 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1803 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1804 if (buffer_format->cs.bold) {
1805 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1806 GINT_TO_POINTER (buffer_format->bold&0x1));
1808 if (buffer_format->cs.italic) {
1809 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1810 GINT_TO_POINTER (buffer_format->italic&0x1));
1812 if (buffer_format->cs.color) {
1813 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1814 GINT_TO_POINTER (&(buffer_format->color)));
1816 if (buffer_format->cs.font_size) {
1817 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1818 GINT_TO_POINTER (buffer_format->font_size));
1820 if (buffer_format->cs.justification) {
1821 switch (buffer_format->justification) {
1822 case GTK_JUSTIFY_LEFT:
1823 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1824 GINT_TO_POINTER(TRUE));
1826 case GTK_JUSTIFY_CENTER:
1827 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1828 GINT_TO_POINTER(TRUE));
1830 case GTK_JUSTIFY_RIGHT:
1831 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1832 GINT_TO_POINTER(TRUE));
1839 if (buffer_format->cs.font) {
1840 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1841 GINT_TO_POINTER (buffer_format->font));
1843 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1844 if (buffer_format->cs.bullet) {
1845 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1846 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1848 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1850 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1852 g_free (buffer_format);
1853 g_free (current_format);
1855 /* Check dimming rules */
1856 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1857 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1861 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1863 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1865 ModestWindowPrivate *parent_priv;
1866 ModestMsgEditWindowPrivate *priv;
1868 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1869 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1871 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1872 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1873 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1874 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1876 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1877 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1878 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1881 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1883 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1884 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1886 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1887 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1889 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1890 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1893 switch (buffer_format->justification)
1895 case GTK_JUSTIFY_LEFT:
1896 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1898 case GTK_JUSTIFY_CENTER:
1899 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1901 case GTK_JUSTIFY_RIGHT:
1902 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1909 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1911 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1912 G_CALLBACK (modest_msg_edit_window_color_button_change),
1914 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1915 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1916 G_CALLBACK (modest_msg_edit_window_color_button_change),
1919 if (priv->current_size_index != buffer_format->font_size) {
1923 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
1924 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
1928 priv->current_size_index = buffer_format->font_size;
1930 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
1931 markup = g_strconcat ("<span font_family='Sans'>",
1932 size_text, "</span>", NULL);
1934 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1938 gtk_tree_path_free (path);
1941 if (priv->current_face_index != buffer_format->font) {
1945 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
1946 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
1950 priv->current_face_index = buffer_format->font;
1951 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
1952 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
1953 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1960 g_free (buffer_format);
1964 #ifdef MODEST_HILDON_VERSION_0
1966 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1969 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1970 ModestMsgEditWindowPrivate *priv;
1971 GtkWidget *dialog = NULL;
1973 GdkColor *new_color = NULL;
1975 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1976 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1978 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1979 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1980 g_free (buffer_format);
1982 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
1983 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1984 if (new_color != NULL) {
1985 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1986 (gpointer) new_color);
1989 gtk_widget_destroy (dialog);
1994 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1997 ModestMsgEditWindowPrivate *priv;
1998 GtkWidget *dialog = NULL;
2000 GdkColor *old_color = NULL;
2001 const GdkColor *new_color = NULL;
2003 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2004 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2006 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2007 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2009 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2010 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2011 if (new_color != NULL)
2012 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2014 gtk_widget_destroy (dialog);
2020 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2023 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2024 ModestMsgEditWindowPrivate *priv;
2025 GtkWidget *dialog = NULL;
2027 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2028 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2030 dialog = hildon_color_chooser_new ();
2031 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2032 g_free (buffer_format);
2034 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2036 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2037 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2040 gtk_widget_destroy (dialog);
2045 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2048 ModestMsgEditWindowPrivate *priv;
2049 GtkWidget *dialog = NULL;
2050 GdkColor *old_color = NULL;
2052 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2053 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2055 dialog = hildon_color_chooser_new ();
2056 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2058 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2060 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2061 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2063 gtk_widget_destroy (dialog);
2066 #endif /*!MODEST_HILDON_VERSION_0*/
2071 create_stream_for_uri (const gchar* uri)
2076 TnyStream *result = NULL;
2078 GnomeVFSHandle *handle = NULL;
2079 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2080 if (test == GNOME_VFS_OK) {
2081 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2082 /* Streams over OBEX (Bluetooth) are not seekable but
2083 * we expect them to be (we might need to read them
2084 * several times). So if this is a Bluetooth URI just
2085 * read the whole file into memory (this is not a fast
2086 * protocol so we can assume that these files are not
2087 * going to be very big) */
2088 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2089 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2090 TnyStream *memstream = tny_camel_mem_stream_new ();
2091 tny_stream_write_to_stream (vfssstream, memstream);
2092 g_object_unref (vfssstream);
2095 result = vfssstream;
2103 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2106 ModestMsgEditWindowPrivate *priv;
2107 GtkWidget *dialog = NULL;
2109 GSList *uris = NULL;
2110 GSList *uri_node = NULL;
2112 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2114 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2115 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2116 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2118 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2120 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2121 GTK_WINDOW (dialog), GTK_WINDOW (window));
2123 response = gtk_dialog_run (GTK_DIALOG (dialog));
2125 case GTK_RESPONSE_OK:
2126 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2131 gtk_widget_destroy (dialog);
2133 g_object_ref (window);
2134 /* The operation could take some time so allow the dialog to be closed */
2135 while (gtk_events_pending ())
2136 gtk_main_iteration ();
2138 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2140 GnomeVFSHandle *handle = NULL;
2141 GnomeVFSResult result;
2142 GtkTextIter position;
2143 GtkTextMark *insert_mark;
2145 uri = (const gchar *) uri_node->data;
2146 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2147 if (result == GNOME_VFS_OK) {
2149 GnomeVFSFileInfo *info;
2150 gchar *filename, *basename, *escaped_filename;
2151 TnyMimePart *mime_part;
2153 const gchar *mime_type = NULL;
2154 GnomeVFSURI *vfs_uri;
2155 guint64 stream_size;
2157 gnome_vfs_close (handle);
2158 vfs_uri = gnome_vfs_uri_new (uri);
2160 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2161 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2162 g_free (escaped_filename);
2163 gnome_vfs_uri_unref (vfs_uri);
2164 info = gnome_vfs_file_info_new ();
2166 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2167 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2169 mime_type = gnome_vfs_file_info_get_mime_type (info);
2171 mime_part = tny_platform_factory_new_mime_part
2172 (modest_runtime_get_platform_factory ());
2174 TnyStream *stream = create_stream_for_uri (uri);
2176 if (stream == NULL) {
2178 modest_platform_information_banner (NULL, NULL,
2179 _FM("sfil_ib_opening_not_allowed"));
2181 g_object_unref (mime_part);
2182 gnome_vfs_file_info_unref (info);
2186 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2188 content_id = g_strdup_printf ("%d", priv->next_cid);
2189 tny_mime_part_set_content_id (mime_part, content_id);
2190 g_free (content_id);
2193 basename = g_path_get_basename (filename);
2194 tny_mime_part_set_filename (mime_part, basename);
2197 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2199 if (pixbuf != NULL) {
2200 priv->images_size += stream_size;
2201 priv->images_count ++;
2202 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2203 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2204 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2205 g_object_unref (pixbuf);
2207 tny_list_prepend (priv->images, (GObject *) mime_part);
2208 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2210 modest_platform_information_banner (NULL, NULL,
2211 _("mail_ib_file_operation_failed"));
2215 g_object_unref (mime_part);
2216 gnome_vfs_file_info_unref (info);
2220 g_object_unref (window);
2224 on_attach_file_response (GtkDialog *dialog,
2228 GSList *uris = NULL;
2230 GnomeVFSFileSize total_size, allowed_size;
2231 ModestMsgEditWindow *window;
2232 ModestMsgEditWindowPrivate *priv;
2237 case GTK_RESPONSE_OK:
2238 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2244 window = MODEST_MSG_EDIT_WINDOW (user_data);
2245 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2247 /* allowed size is the maximum size - what's already there */
2248 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2249 &att_num, &att_size);
2250 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2253 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2255 const gchar *uri = (const gchar *) uri_node->data;
2258 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2260 if (total_size > allowed_size) {
2261 g_warning ("%s: total size: %u",
2262 __FUNCTION__, (unsigned int)total_size);
2265 allowed_size -= total_size;
2267 g_slist_foreach (uris, (GFunc) g_free, NULL);
2268 g_slist_free (uris);
2270 gtk_widget_destroy (GTK_WIDGET (dialog));
2274 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2276 GtkWidget *dialog = NULL;
2277 ModestMsgEditWindowPrivate *priv;
2279 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2281 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2283 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2286 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2287 GTK_FILE_CHOOSER_ACTION_OPEN);
2288 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2289 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2290 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2291 GTK_WINDOW (dialog), GTK_WINDOW (window));
2293 /* Connect to response & show */
2294 g_signal_connect (dialog, "response",
2295 G_CALLBACK (on_attach_file_response), window);
2296 gtk_widget_show (dialog);
2301 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2303 GnomeVFSFileSize allowed_size)
2306 GnomeVFSHandle *handle = NULL;
2307 ModestMsgEditWindowPrivate *priv;
2308 GnomeVFSResult result;
2309 GnomeVFSFileSize size = 0;
2310 g_return_val_if_fail (window, 0);
2311 g_return_val_if_fail (uri, 0);
2313 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2315 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2316 if (result == GNOME_VFS_OK) {
2317 TnyMimePart *mime_part;
2319 const gchar *mime_type = NULL;
2321 gchar *escaped_filename;
2324 GnomeVFSFileInfo *info;
2325 GnomeVFSURI *vfs_uri;
2327 gnome_vfs_close (handle);
2328 vfs_uri = gnome_vfs_uri_new (uri);
2331 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2332 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2333 g_free (escaped_filename);
2334 gnome_vfs_uri_unref (vfs_uri);
2336 info = gnome_vfs_file_info_new ();
2338 if (gnome_vfs_get_file_info (uri,
2340 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2342 mime_type = gnome_vfs_file_info_get_mime_type (info);
2343 mime_part = tny_platform_factory_new_mime_part
2344 (modest_runtime_get_platform_factory ());
2346 /* try to get the attachment's size; this may fail for weird
2347 * file systems, like obex, upnp... */
2348 if (allowed_size != 0 &&
2349 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2351 if (size > allowed_size) {
2352 modest_platform_information_banner (NULL, NULL,
2353 _FM("sfil_ib_opening_not_allowed"));
2357 g_warning ("%s: could not get attachment size", __FUNCTION__);
2359 stream = create_stream_for_uri (uri);
2361 if (stream == NULL) {
2363 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2365 g_object_unref (mime_part);
2366 gnome_vfs_file_info_unref (info);
2370 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2371 g_object_unref (stream);
2373 content_id = g_strdup_printf ("%d", priv->next_cid);
2374 tny_mime_part_set_content_id (mime_part, content_id);
2375 g_free (content_id);
2378 basename = g_path_get_basename (filename);
2379 tny_mime_part_set_filename (mime_part, basename);
2382 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2383 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2385 info->size == 0, info->size);
2386 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2387 gtk_widget_show_all (priv->attachments_caption);
2388 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2390 g_object_unref (mime_part);
2391 gnome_vfs_file_info_unref (info);
2398 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2401 ModestMsgEditWindowPrivate *priv;
2404 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2405 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2407 if (att_list == NULL) {
2408 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2409 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2410 g_object_unref (att_list);
2415 g_object_ref (att_list);
2418 if (tny_list_get_length (att_list) == 0) {
2419 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2421 gboolean dialog_response;
2422 gchar *message = NULL;
2423 gchar *filename = NULL;
2425 if (tny_list_get_length (att_list) == 1) {
2427 iter = tny_list_create_iterator (att_list);
2428 part = (TnyMimePart *) tny_iterator_get_current (iter);
2429 g_object_unref (iter);
2430 if (TNY_IS_MSG (part)) {
2431 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2433 filename = tny_header_dup_subject (header);
2434 g_object_unref (header);
2436 if (filename == NULL) {
2437 filename = g_strdup (_("mail_va_no_subject"));
2440 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2442 g_object_unref (part);
2444 filename = g_strdup ("");
2446 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2447 "emev_nc_delete_attachments",
2448 tny_list_get_length (att_list)), filename);
2451 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2455 if (dialog_response != GTK_RESPONSE_OK) {
2456 g_object_unref (att_list);
2460 for (iter = tny_list_create_iterator (att_list);
2461 !tny_iterator_is_done (iter);
2462 tny_iterator_next (iter)) {
2463 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2464 const gchar *att_id;
2465 tny_list_remove (priv->attachments, (GObject *) mime_part);
2467 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2469 if (tny_list_get_length (priv->attachments) == 0)
2470 gtk_widget_hide (priv->attachments_caption);
2471 att_id = tny_mime_part_get_content_id (mime_part);
2473 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2475 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2476 g_object_unref (mime_part);
2478 g_object_unref (iter);
2481 g_object_unref (att_list);
2483 /* if the last attachment has been removed, focus the Subject: field */
2484 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2485 gtk_widget_grab_focus (priv->subject_field);
2489 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2492 ModestMsgEditWindowPrivate *priv;
2493 GdkColor *new_color;
2494 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2496 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2497 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2500 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2502 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2504 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2506 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2511 font_size_clicked (GtkToolButton *button,
2512 ModestMsgEditWindow *window)
2514 ModestMsgEditWindowPrivate *priv;
2515 GtkWidget *selector, *dialog;
2517 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2519 selector = hildon_touch_selector_new ();
2520 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2521 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2523 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2524 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2526 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2530 WPTextBufferFormat format;
2532 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2534 memset (&format, 0, sizeof (format));
2535 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2537 format.cs.font_size = TRUE;
2538 format.cs.text_position = TRUE;
2539 format.cs.font = TRUE;
2540 format.font_size = new_index;
2541 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2543 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2544 GINT_TO_POINTER (new_index)))
2545 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2547 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2548 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2549 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2550 size_text, "</span>", NULL);
2552 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2556 gtk_widget_destroy (dialog);
2558 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2563 font_face_clicked (GtkToolButton *button,
2564 ModestMsgEditWindow *window)
2566 ModestMsgEditWindowPrivate *priv;
2567 GtkWidget *selector, *dialog;
2568 GtkCellRenderer *renderer;
2570 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2572 selector = hildon_touch_selector_new ();
2573 renderer = gtk_cell_renderer_text_new ();
2574 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2575 renderer, "family", 0, "text", 0, NULL);
2576 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2578 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2579 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2581 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2582 gint new_font_index;
2586 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2587 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2588 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2592 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2594 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2595 GINT_TO_POINTER(new_font_index)))
2596 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2598 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2599 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2601 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2605 gtk_tree_path_free (path);
2608 gtk_widget_destroy (dialog);
2610 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2615 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2618 ModestMsgEditWindowPrivate *priv = NULL;
2619 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2621 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2622 if (!priv->update_caption_visibility)
2625 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2627 gtk_widget_show (priv->cc_caption);
2629 gtk_widget_hide (priv->cc_caption);
2631 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2635 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2638 ModestMsgEditWindowPrivate *priv = NULL;
2639 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2641 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2642 if (!priv->update_caption_visibility)
2645 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2647 gtk_widget_show (priv->bcc_caption);
2649 gtk_widget_hide (priv->bcc_caption);
2651 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2655 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2656 ModestRecptEditor *editor)
2658 ModestMsgEditWindowPrivate *priv;
2660 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2661 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2663 /* we check for low-mem; in that case, show a warning, and don't allow
2664 * for the addressbook
2666 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2669 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2671 if (editor == NULL) {
2672 GtkWidget *view_focus;
2673 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2675 /* This code should be kept in sync with ModestRecptEditor. The
2676 textview inside the recpt editor is the one that really gets the
2677 focus. As it's inside a scrolled window, and this one inside the
2678 hbox recpt editor inherits from, we'll need to go up in the
2679 hierarchy to know if the text view is part of the recpt editor
2680 or if it's a different text entry */
2682 if (gtk_widget_get_parent (view_focus)) {
2683 GtkWidget *first_parent;
2685 first_parent = gtk_widget_get_parent (view_focus);
2686 if (gtk_widget_get_parent (first_parent) &&
2687 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2688 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2693 editor = MODEST_RECPT_EDITOR (priv->to_field);
2697 modest_address_book_select_addresses (editor);
2702 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2704 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2706 modest_msg_edit_window_open_addressbook (window, NULL);
2710 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2711 gboolean show_toolbar)
2713 ModestWindowPrivate *parent_priv;
2715 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2716 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2718 /* We can not just use the code of
2719 modest_msg_edit_window_setup_toolbar because it has a
2720 mixture of both initialization and creation code. */
2722 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2724 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2728 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2729 TnyHeaderFlags priority_flags)
2731 ModestMsgEditWindowPrivate *priv;
2732 ModestWindowPrivate *parent_priv;
2734 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2736 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2737 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2739 if (priv->priority_flags != priority_flags) {
2740 GtkAction *priority_action = NULL;
2742 priv->priority_flags = priority_flags;
2744 switch (priority_flags) {
2745 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2746 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2747 MODEST_HEADER_ICON_HIGH,
2748 HILDON_ICON_SIZE_SMALL);
2749 gtk_widget_show (priv->priority_icon);
2750 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2751 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2753 case TNY_HEADER_FLAG_LOW_PRIORITY:
2754 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2755 MODEST_HEADER_ICON_LOW,
2756 HILDON_ICON_SIZE_SMALL);
2757 gtk_widget_show (priv->priority_icon);
2758 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2759 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2762 gtk_widget_hide (priv->priority_icon);
2763 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2764 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2767 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2768 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2770 gtk_widget_queue_resize (priv->subject_box);
2774 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2777 ModestMsgEditWindowPrivate *priv;
2778 ModestWindowPrivate *parent_priv;
2779 gint current_format;
2781 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2783 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2784 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2786 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2787 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2789 if (current_format != file_format) {
2790 switch (file_format) {
2791 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2792 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2793 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2795 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2799 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2800 response = gtk_dialog_run (GTK_DIALOG (dialog));
2801 gtk_widget_destroy (dialog);
2802 if (response == GTK_RESPONSE_OK) {
2803 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2805 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2806 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2811 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2812 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2813 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2818 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2821 ModestMsgEditWindowPrivate *priv;
2822 WPTextBufferFormat oldfmt, fmt;
2823 gint old_position = 0;
2827 GdkColor *color = NULL;
2828 gboolean bold, bold_set, italic, italic_set;
2829 gboolean underline, underline_set;
2830 gboolean strikethrough, strikethrough_set;
2831 gboolean position_set;
2832 gboolean font_size_set, font_set, color_set;
2835 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2836 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2838 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2839 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2840 GTK_WINDOW(dialog), GTK_WINDOW (window));
2842 /* First we get the currently selected font information */
2843 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2845 switch (oldfmt.text_position) {
2846 case TEXT_POSITION_NORMAL:
2849 case TEXT_POSITION_SUPERSCRIPT:
2857 g_object_set (G_OBJECT (dialog),
2858 "bold", oldfmt.bold != FALSE,
2859 "bold-set", !oldfmt.cs.bold,
2860 "underline", oldfmt.underline != FALSE,
2861 "underline-set", !oldfmt.cs.underline,
2862 "italic", oldfmt.italic != FALSE,
2863 "italic-set", !oldfmt.cs.italic,
2864 "strikethrough", oldfmt.strikethrough != FALSE,
2865 "strikethrough-set", !oldfmt.cs.strikethrough,
2866 "color", &oldfmt.color,
2867 "color-set", !oldfmt.cs.color,
2868 "size", wp_font_size[oldfmt.font_size],
2869 "size-set", !oldfmt.cs.font_size,
2870 "position", old_position,
2871 "position-set", !oldfmt.cs.text_position,
2872 "family", wp_get_font_name (oldfmt.font),
2873 "family-set", !oldfmt.cs.font,
2876 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2877 GTK_WINDOW (dialog), GTK_WINDOW (window));
2878 gtk_widget_show_all (dialog);
2879 priv->font_dialog = dialog;
2880 response = gtk_dialog_run (GTK_DIALOG (dialog));
2881 priv->font_dialog = NULL;
2882 if (response == GTK_RESPONSE_OK) {
2884 g_object_get( dialog,
2886 "bold-set", &bold_set,
2887 "underline", &underline,
2888 "underline-set", &underline_set,
2890 "italic-set", &italic_set,
2891 "strikethrough", &strikethrough,
2892 "strikethrough-set", &strikethrough_set,
2894 "color-set", &color_set,
2896 "size-set", &font_size_set,
2897 "family", &font_name,
2898 "family-set", &font_set,
2899 "position", &position,
2900 "position-set", &position_set,
2905 if (response == GTK_RESPONSE_OK) {
2906 memset(&fmt, 0, sizeof(fmt));
2912 fmt.italic = italic;
2913 fmt.cs.italic = TRUE;
2915 if (underline_set) {
2916 fmt.underline = underline;
2917 fmt.cs.underline = TRUE;
2919 if (strikethrough_set) {
2920 fmt.strikethrough = strikethrough;
2921 fmt.cs.strikethrough = TRUE;
2926 ? TEXT_POSITION_NORMAL
2927 : ( ( position == 1 )
2928 ? TEXT_POSITION_SUPERSCRIPT
2929 : TEXT_POSITION_SUBSCRIPT );
2930 fmt.cs.text_position = TRUE;
2931 fmt.font_size = oldfmt.font_size;
2935 fmt.cs.color = TRUE;
2938 fmt.font = wp_get_font_index(font_name,
2943 if (font_size_set) {
2944 fmt.cs.font_size = TRUE;
2945 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2947 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2948 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2950 gtk_widget_destroy (dialog);
2952 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2956 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2958 ModestMsgEditWindowPrivate *priv;
2960 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2961 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2963 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2965 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2966 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2970 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2972 ModestMsgEditWindowPrivate *priv;
2974 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2975 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2977 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2979 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2980 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2985 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2987 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2989 priv->can_undo = can_undo;
2993 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2995 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2997 priv->can_redo = can_redo;
3001 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3003 ModestMsgEditWindowPrivate *priv;
3004 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3005 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3007 return priv->can_undo;
3011 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3013 ModestMsgEditWindowPrivate *priv;
3014 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3015 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3017 return priv->can_redo;
3022 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3025 GtkTextIter match_start, match_end;
3027 if (image_id == NULL)
3030 gtk_text_buffer_get_start_iter (buffer, &iter);
3032 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3033 GSList *tags = gtk_text_iter_get_tags (&match_start);
3035 for (node = tags; node != NULL; node = g_slist_next (node)) {
3036 GtkTextTag *tag = (GtkTextTag *) node->data;
3037 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3038 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3039 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3041 offset = gtk_text_iter_get_offset (&match_start);
3042 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3043 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3047 gtk_text_iter_forward_char (&iter);
3052 message_is_empty (ModestMsgEditWindow *window)
3054 ModestMsgEditWindowPrivate *priv = NULL;
3056 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3057 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3059 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3060 * so we can ignore markup.
3062 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3065 count = gtk_text_buffer_get_char_count (buf);
3071 msg_body_focus (GtkWidget *focus,
3072 GdkEventFocus *event,
3076 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3077 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3078 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3083 recpt_field_changed (GtkTextBuffer *buffer,
3084 ModestMsgEditWindow *editor)
3086 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3087 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3091 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3093 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3094 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3098 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3101 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3102 GtkTextBuffer *buffer;
3104 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3105 gtk_text_buffer_set_modified (buffer, modified);
3106 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3107 gtk_text_buffer_set_modified (buffer, modified);
3108 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3109 gtk_text_buffer_set_modified (buffer, modified);
3110 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3114 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3116 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3117 const char *account_name;
3118 GtkTextBuffer *buffer;
3120 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3121 if (gtk_text_buffer_get_modified (buffer))
3123 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3124 if (gtk_text_buffer_get_modified (buffer))
3126 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3127 if (gtk_text_buffer_get_modified (buffer))
3129 if (gtk_text_buffer_get_modified (priv->text_buffer))
3131 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3132 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3143 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3145 ModestMsgEditWindowPrivate *priv = NULL;
3147 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3148 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3150 /* check if there's no recipient added */
3151 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3152 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3153 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3154 /* no recipient contents, then select contacts */
3155 modest_msg_edit_window_open_addressbook (window, NULL);
3159 g_object_ref (window);
3160 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3161 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3162 g_object_unref (window);
3165 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3166 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3167 g_object_unref (window);
3170 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3171 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3172 g_object_unref (window);
3176 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3177 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3178 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3179 g_object_unref (window);
3186 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3187 ModestMsgEditWindow *window)
3189 modest_msg_edit_window_offer_attach_file (window);
3193 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3195 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3197 return priv->clipboard_text;
3201 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3203 ModestMsgEditWindow *window)
3205 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3206 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3208 if (!GTK_WIDGET_VISIBLE (window))
3211 g_object_ref (window);
3212 text = gtk_clipboard_wait_for_text (selection_clipboard);
3214 if (priv->clipboard_text != NULL) {
3215 g_free (priv->clipboard_text);
3217 priv->clipboard_text = text;
3219 if (GTK_WIDGET_VISIBLE (window)) {
3220 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3222 g_object_unref (window);
3225 static gboolean clipboard_owner_change_idle (gpointer userdata)
3227 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3228 ModestMsgEditWindowPrivate *priv;
3230 gdk_threads_enter ();
3231 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3232 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3234 priv->clipboard_owner_idle = 0;
3235 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3236 gdk_threads_leave ();
3242 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3244 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3245 if (priv->clipboard_owner_idle == 0) {
3246 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3251 subject_field_move_cursor (GtkEntry *entry,
3252 GtkMovementStep step,
3257 if (!GTK_WIDGET_VISIBLE (window))
3260 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3264 update_window_title (ModestMsgEditWindow *window)
3266 ModestMsgEditWindowPrivate *priv = NULL;
3267 const gchar *subject;
3269 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3270 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3271 if (subject == NULL || subject[0] == '\0')
3272 subject = _("mail_va_new_email");
3274 gtk_window_set_title (GTK_WINDOW (window), subject);
3279 subject_field_changed (GtkEditable *editable,
3280 ModestMsgEditWindow *window)
3282 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3283 update_window_title (window);
3284 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3285 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3286 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3290 subject_field_insert_text (GtkEditable *editable,
3292 gint new_text_length,
3294 ModestMsgEditWindow *window)
3296 GString *result = g_string_new ("");
3298 gint result_len = 0;
3299 const gchar *entry_text = NULL;
3302 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3303 old_length = g_utf8_strlen (entry_text, -1);
3305 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3306 gunichar c = g_utf8_get_char_validated (current, 8);
3307 /* Invalid unichar, stop */
3313 result = g_string_append_unichar (result, c);
3317 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3318 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3321 /* Prevent endless recursion */
3322 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3323 g_signal_emit_by_name (editable, "insert-text",
3324 (gpointer) result->str, (gpointer) result->len,
3325 (gpointer) position, (gpointer) window);
3326 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3330 if (result_len + old_length > 1000) {
3331 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3332 _CS("ckdg_ib_maximum_characters_reached"));
3334 g_string_free (result, TRUE);
3338 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3341 ModestMsgEditWindowPrivate *priv = NULL;
3343 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3344 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3346 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3349 gtk_widget_show_all (priv->find_toolbar);
3350 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3352 gtk_widget_hide_all (priv->find_toolbar);
3353 gtk_widget_grab_focus (priv->msg_body);
3358 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3360 GtkTextIter *match_start,
3361 GtkTextIter *match_end)
3363 GtkTextIter end_iter;
3364 gchar *str_casefold;
3367 gchar *range_casefold;
3370 gboolean result = FALSE;
3377 gtk_text_iter_forward_to_end (&end_iter);
3379 str_casefold = g_utf8_casefold (str, -1);
3380 str_chars_n = strlen (str);
3382 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3383 range_casefold = g_utf8_casefold (range_text, -1);
3384 range_chars_n = strlen (range_casefold);
3386 if (range_chars_n < str_chars_n) {
3387 g_free (str_casefold);
3388 g_free (range_text);
3389 g_free (range_casefold);
3393 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3394 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3395 if (!g_utf8_collate (range_subtext, str_casefold)) {
3396 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3398 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3399 match_start, match_end, NULL);
3400 g_free (found_text);
3402 g_free (range_subtext);
3406 g_free (str_casefold);
3407 g_free (range_text);
3408 g_free (range_casefold);
3415 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3416 ModestMsgEditWindow *window)
3418 gchar *current_search = NULL;
3419 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3421 GtkTextIter selection_start, selection_end;
3422 GtkTextIter match_start, match_end;
3423 gboolean continue_search = FALSE;
3425 if (message_is_empty (window)) {
3426 g_free (priv->last_search);
3427 priv->last_search = NULL;
3428 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3432 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3433 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3434 g_free (current_search);
3435 g_free (priv->last_search);
3436 priv->last_search = NULL;
3437 /* Information banner about empty search */
3438 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3442 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3443 continue_search = TRUE;
3445 g_free (priv->last_search);
3446 priv->last_search = g_strdup (current_search);
3449 if (continue_search) {
3450 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3451 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3452 &match_start, &match_end);
3454 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3456 GtkTextIter buffer_start;
3457 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3458 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3459 &match_start, &match_end);
3461 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3464 /* Mark as selected the string found in search */
3466 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3467 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3468 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3470 g_free (priv->last_search);
3471 priv->last_search = NULL;
3473 g_free (current_search);
3477 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3479 ModestMsgEditWindowPrivate *priv;
3481 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3486 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3489 ModestMsgEditWindowPrivate *priv;
3491 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3496 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3497 ModestMsgEditWindow *window)
3499 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3503 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3506 ModestMsgEditWindowPrivate *priv;
3507 TnyHeader *header = NULL;
3509 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3510 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3512 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3513 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3515 if (priv->draft_msg != NULL) {
3516 g_object_unref (priv->draft_msg);
3519 if (draft != NULL) {
3520 g_object_ref (draft);
3521 header = tny_msg_get_header (draft);
3522 if (priv->msg_uid) {
3523 g_free (priv->msg_uid);
3524 priv->msg_uid = NULL;
3526 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3527 if (GTK_WIDGET_REALIZED (window)) {
3528 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3529 gtk_widget_destroy (GTK_WIDGET (window));
3535 priv->draft_msg = draft;
3539 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3540 GtkTextIter *start, GtkTextIter *end,
3543 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3544 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3547 if (tag == NULL) return;
3548 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3549 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3550 replace_with_images (window, priv->images);
3555 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3558 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3560 g_return_if_fail (TNY_IS_MIME_PART (part));
3561 tny_list_prepend (priv->attachments, (GObject *) part);
3562 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3563 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3564 gtk_widget_show_all (priv->attachments_caption);
3565 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3569 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3571 ModestMsgEditWindowPrivate *priv;
3573 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3574 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3576 return priv->msg_uid;
3580 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3581 ModestMsgEditWindowWidgetType widget_type)
3583 ModestMsgEditWindowPrivate *priv;
3585 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3586 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3588 switch (widget_type) {
3589 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3590 return priv->msg_body;
3592 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3593 return priv->to_field;
3595 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3596 return priv->cc_field;
3598 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3599 return priv->bcc_field;
3601 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3602 return priv->subject_field;
3604 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3605 return priv->attachments_view;
3613 remove_tags (WPTextBuffer *buffer)
3615 GtkTextIter start, end;
3617 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3618 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3620 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3624 on_account_removed (TnyAccountStore *account_store,
3625 TnyAccount *account,
3628 /* Do nothing if it's a store account, because we use the
3629 transport to send the messages */
3630 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3631 const gchar *parent_acc = NULL;
3632 const gchar *our_acc = NULL;
3634 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3635 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3636 /* Close this window if I'm showing a message of the removed account */
3637 if (strcmp (parent_acc, our_acc) == 0)
3638 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3643 from_field_changed (HildonPickerButton *button,
3644 ModestMsgEditWindow *self)
3646 ModestMsgEditWindowPrivate *priv;
3647 gboolean has_old_signature, has_new_signature;
3649 GtkTextIter match_start, match_end;
3650 ModestAccountMgr *mgr;
3652 gchar *full_signature;
3654 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3656 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3657 mgr = modest_runtime_get_account_mgr ();
3658 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3659 if (has_old_signature) {
3660 full_signature = g_strconcat ("\n--\n", signature, NULL);
3661 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3662 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3664 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3665 &match_start, &match_end, NULL)) {
3668 g_free (full_signature);
3672 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3673 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3674 if (has_new_signature) {
3675 full_signature = g_strconcat ("\n--\n", signature, NULL);
3676 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3677 g_free (full_signature);
3682 typedef struct _MessageSettingsHelper {
3683 ModestMsgEditWindow *window;
3684 GSList *priority_group;
3685 GSList *format_group;
3686 GtkToggleButton *current_priority;
3687 GtkToggleButton *current_format;
3688 } MessageSettingsHelper;
3691 on_priority_toggle (GtkToggleButton *button,
3692 MessageSettingsHelper *helper)
3695 ModestMsgEditWindowPrivate *priv;
3697 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3698 if (gtk_toggle_button_get_active (button)) {
3700 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3701 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3702 if ((node_button != button) &&
3703 gtk_toggle_button_get_active (node_button)) {
3704 gtk_toggle_button_set_active (node_button, FALSE);
3707 helper->current_priority = button;
3709 gboolean found = FALSE;
3710 /* If no one is active, activate it again */
3711 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3712 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3713 if (gtk_toggle_button_get_active (node_button)) {
3719 gtk_toggle_button_set_active (button, TRUE);
3725 on_format_toggle (GtkToggleButton *button,
3726 MessageSettingsHelper *helper)
3729 ModestMsgEditWindowPrivate *priv;
3731 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3732 if (gtk_toggle_button_get_active (button)) {
3734 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3735 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3736 if ((node_button != button) &&
3737 gtk_toggle_button_get_active (node_button)) {
3738 gtk_toggle_button_set_active (node_button, FALSE);
3741 helper->current_format = button;
3743 gboolean found = FALSE;
3744 /* If no one is active, activate it again */
3745 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3746 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3747 if (gtk_toggle_button_get_active (node_button)) {
3753 gtk_toggle_button_set_active (button, TRUE);
3760 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3765 GtkWidget *priority_hbox;
3766 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3767 GtkWidget *captioned;
3768 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3769 GtkWidget *format_hbox;
3770 GtkWidget *html_toggle, *text_toggle;
3771 ModestMsgEditWindowPrivate *priv;
3772 MessageSettingsHelper helper = {0,};
3774 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3775 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3776 helper.window = window;
3777 helper.priority_group = NULL;
3778 helper.format_group = NULL;
3780 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3781 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3783 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3784 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3785 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3786 vbox = gtk_vbox_new (FALSE, 0);
3787 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
3788 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
3789 gtk_container_add (GTK_CONTAINER (align), vbox);
3790 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
3791 gtk_widget_show (align);
3792 gtk_widget_show (vbox);
3794 /* Priority toggles */
3795 priority_hbox = gtk_hbox_new (TRUE, 0);
3796 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3797 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3798 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3799 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3800 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3801 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3802 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3803 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3804 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3805 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3806 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3807 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3808 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3809 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3810 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3811 gtk_widget_show_all (priority_hbox);
3812 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3813 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3814 gtk_widget_show (captioned);
3815 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3817 /* format toggles */
3818 format_hbox = gtk_hbox_new (TRUE, 0);
3819 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3820 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3821 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3822 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3823 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3824 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3825 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3826 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3827 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3828 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3829 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3830 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3831 gtk_widget_show_all (format_hbox);
3832 gtk_widget_show (format_hbox);
3833 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3836 g_object_unref (title_sizegroup);
3837 g_object_unref (value_sizegroup);
3839 /* Set current values */
3840 switch (priv->priority_flags) {
3841 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3842 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3843 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3845 case TNY_HEADER_FLAG_LOW_PRIORITY:
3846 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3847 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3850 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3851 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3855 switch (modest_msg_edit_window_get_format (window)) {
3856 case MODEST_MSG_EDIT_FORMAT_TEXT:
3857 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3858 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3860 case MODEST_MSG_EDIT_FORMAT_HTML:
3862 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3863 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3867 /* Signal connects */
3868 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3869 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3870 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3871 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3872 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3874 /* Save settings if the user clicked on done */
3875 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3876 TnyHeaderFlags flags;
3877 ModestMsgEditFormat old_format, new_format;
3879 /* Set priority flags */
3880 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3881 if (priv->priority_flags != flags)
3882 modest_msg_edit_window_set_priority_flags (window, flags);
3884 /* Set edit format */
3885 old_format = modest_msg_edit_window_get_format (window);
3886 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3887 if (old_format != new_format) {
3888 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3889 modest_msg_edit_window_set_file_format (window, file_format);
3893 gtk_widget_destroy (dialog);
3894 g_slist_free (helper.priority_group);
3898 on_message_settings (GtkAction *action,
3899 ModestMsgEditWindow *window)
3901 modest_msg_edit_window_show_msg_settings_dialog (window);
3905 on_cc_button_toggled (HildonCheckButton *button,
3906 ModestMsgEditWindow *window)
3908 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3910 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3911 hildon_check_button_get_active (button));
3915 on_bcc_button_toggled (HildonCheckButton *button,
3916 ModestMsgEditWindow *window)
3918 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3920 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3921 hildon_check_button_get_active (button));
3925 setup_menu (ModestMsgEditWindow *self)
3927 ModestMsgEditWindowPrivate *priv = NULL;
3929 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3931 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3933 /* Settings menu buttons */
3934 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3935 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3937 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3938 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3939 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3941 priv->cc_button = hildon_check_button_new (0);
3942 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3943 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3945 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3947 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3948 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3949 priv->bcc_button = hildon_check_button_new (0);
3950 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3951 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3953 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3955 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3956 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3958 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3959 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3960 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3961 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3962 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3963 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3964 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3965 APP_MENU_CALLBACK (on_message_settings),
3967 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3968 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),