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 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
358 conf = modest_runtime_get_conf ();
360 /* Dim at start clipboard actions */
361 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
362 gtk_action_set_sensitive (action, FALSE);
363 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
364 gtk_action_set_sensitive (action, FALSE);
365 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
366 gtk_action_set_sensitive (action, FALSE);
368 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
373 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
375 GObjectClass *gobject_class;
376 ModestWindowClass *modest_window_class;
377 gobject_class = (GObjectClass*) klass;
378 modest_window_class = (ModestWindowClass*) klass;
380 parent_class = g_type_class_peek_parent (klass);
381 gobject_class->finalize = modest_msg_edit_window_finalize;
383 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
384 modest_window_class->save_state_func = save_state;
385 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
387 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
391 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
393 ModestMsgEditWindowPrivate *priv;
394 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
396 priv->msg_body = NULL;
397 priv->from_field = NULL;
398 priv->to_field = NULL;
399 priv->cc_field = NULL;
400 priv->bcc_field = NULL;
401 priv->subject_field = NULL;
402 priv->attachments = TNY_LIST (tny_simple_list_new ());
403 priv->images = TNY_LIST (tny_simple_list_new ());
404 priv->images_size = 0;
405 priv->images_count = 0;
408 priv->cc_caption = NULL;
409 priv->bcc_caption = NULL;
410 priv->update_caption_visibility = FALSE;
412 priv->priority_flags = 0;
414 priv->find_toolbar = NULL;
415 priv->last_search = NULL;
417 priv->draft_msg = NULL;
418 priv->outbox_msg = NULL;
419 priv->msg_uid = NULL;
421 priv->can_undo = FALSE;
422 priv->can_redo = FALSE;
423 priv->clipboard_change_handler_id = 0;
424 priv->default_clipboard_change_handler_id = 0;
425 priv->account_removed_handler_id = 0;
426 priv->clipboard_owner_idle = 0;
427 priv->clipboard_text = NULL;
430 priv->scroll_drag_timeout_id = 0;
431 priv->correct_scroll_idle = 0;
432 priv->last_upper = 0.0;
434 priv->font_dialog = NULL;
435 priv->app_menu = NULL;
437 if (!is_wp_text_buffer_started) {
438 is_wp_text_buffer_started = TRUE;
439 wp_text_buffer_library_init ();
444 hildon_program_add_window (hildon_program_get_instance(),
450 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
452 static ModestPairList*
453 get_transports (void)
455 GSList *transports = NULL;
457 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
458 GSList *accounts = modest_account_mgr_account_names (account_mgr,
459 TRUE /* only enabled accounts. */);
461 GSList *cursor = accounts;
463 gchar *account_name = cursor->data;
464 gchar *from_string = NULL;
466 from_string = modest_account_mgr_get_from_string (account_mgr,
470 if (from_string && account_name) {
471 gchar *name = account_name;
472 ModestPair *pair = modest_pair_new ((gpointer) name,
473 (gpointer) from_string , TRUE);
474 transports = g_slist_prepend (transports, pair);
477 cursor = cursor->next;
479 g_slist_free (accounts); /* only free the accounts, not the elements,
480 * because they are used in the pairlist */
484 static void window_focus (GtkWindow *window,
488 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
492 scroll_drag_timeout (gpointer userdata)
494 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
495 ModestMsgEditWindowPrivate *priv;
497 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
499 correct_scroll_without_drag_check (win, TRUE);
501 priv->scroll_drag_timeout_id = 0;
507 correct_scroll_without_drag_check_idle (gpointer userdata)
509 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
510 ModestMsgEditWindowPrivate *priv;
512 GdkRectangle rectangle;
513 gint offset_min, offset_max;
517 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
519 insert = gtk_text_buffer_get_insert (priv->text_buffer);
520 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
522 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
523 offset_min = priv->msg_body->allocation.y + rectangle.y;
524 offset_max = offset_min + rectangle.height;
526 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
527 offset_min = MAX (offset_min - 48, 0);
528 offset_max = MIN (offset_max + 48, vadj->upper);
530 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
532 priv->correct_scroll_idle = 0;
537 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
539 ModestMsgEditWindowPrivate *priv;
541 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
543 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
546 if (priv->correct_scroll_idle > 0) {
550 priv->correct_scroll_idle = g_idle_add ((GSourceFunc) correct_scroll_without_drag_check_idle,
555 correct_scroll (ModestMsgEditWindow *w)
557 ModestMsgEditWindowPrivate *priv;
559 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
560 if (gtk_grab_get_current () == priv->msg_body) {
561 if (priv->scroll_drag_timeout_id == 0) {
562 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
568 correct_scroll_without_drag_check (w, TRUE);
572 text_buffer_end_user_action (GtkTextBuffer *buffer,
573 ModestMsgEditWindow *userdata)
576 correct_scroll (userdata);
580 text_buffer_mark_set (GtkTextBuffer *buffer,
583 ModestMsgEditWindow *userdata)
585 gtk_text_buffer_begin_user_action (buffer);
586 gtk_text_buffer_end_user_action (buffer);
590 cut_clipboard_check (GtkTextView *text_view,
593 GtkTextBuffer *buffer;
595 buffer = gtk_text_view_get_buffer (text_view);
596 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
597 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
602 copy_clipboard_check (GtkTextView *text_view,
605 GtkTextBuffer *buffer;
607 buffer = gtk_text_view_get_buffer (text_view);
608 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
609 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
614 attachment_deleted (ModestAttachmentsView *attachments_view,
617 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
622 connect_signals (ModestMsgEditWindow *obj)
624 ModestMsgEditWindowPrivate *priv;
626 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
628 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
629 G_CALLBACK (text_buffer_refresh_attributes), obj);
630 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
631 G_CALLBACK (text_buffer_can_undo), obj);
632 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
633 G_CALLBACK (text_buffer_can_redo), obj);
634 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
635 G_CALLBACK (body_changed), obj);
636 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
637 G_CALLBACK (body_changed), obj);
638 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
639 G_CALLBACK (text_buffer_end_user_action), obj);
640 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
641 G_CALLBACK (text_buffer_mark_set), obj);
642 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
643 G_CALLBACK (text_buffer_apply_tag), obj);
644 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
645 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
646 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
647 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
648 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
649 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
651 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
652 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
653 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
654 G_CALLBACK (from_field_changed), obj);
656 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
657 G_CALLBACK (msg_body_focus), obj);
658 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
659 G_CALLBACK (msg_body_focus), obj);
660 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
661 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
662 "changed", G_CALLBACK (recpt_field_changed), obj);
663 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
664 "changed", G_CALLBACK (recpt_field_changed), obj);
665 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
666 "changed", G_CALLBACK (recpt_field_changed), obj);
667 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
668 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
669 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
671 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
672 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
674 priv->clipboard_change_handler_id =
675 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
676 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
677 priv->default_clipboard_change_handler_id =
678 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
679 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
681 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
682 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
683 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
687 init_wp_text_view_style ()
689 static gboolean initialized = FALSE;
692 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
698 init_window (ModestMsgEditWindow *obj)
700 GtkWidget *to_caption, *subject_caption;
701 GtkWidget *main_vbox;
702 GtkWidget *add_attachment_align;
703 ModestMsgEditWindowPrivate *priv;
704 GtkActionGroup *action_group;
705 ModestWindowPrivate *parent_priv;
706 GdkPixbuf *window_icon = NULL;
707 GError *error = NULL;
709 GtkSizeGroup *title_size_group;
710 GtkSizeGroup *value_size_group;
711 GtkWidget *attachment_icon;
712 GtkWidget *window_box;
713 GtkWidget *window_align;
714 #if (GTK_MINOR_VERSION >= 10)
715 GdkAtom deserialize_type;
718 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
719 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
721 parent_priv->ui_manager = gtk_ui_manager_new();
722 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
723 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
725 /* Add common actions */
726 gtk_action_group_add_actions (action_group,
727 modest_msg_edit_action_entries,
728 G_N_ELEMENTS (modest_msg_edit_action_entries),
730 gtk_action_group_add_actions (action_group,
731 hildon2_msg_edit_action_entries,
732 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
734 gtk_action_group_add_toggle_actions (action_group,
735 modest_msg_edit_toggle_action_entries,
736 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
738 gtk_action_group_add_radio_actions (action_group,
739 modest_msg_edit_alignment_radio_action_entries,
740 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
742 G_CALLBACK (modest_ui_actions_on_change_justify),
744 gtk_action_group_add_radio_actions (action_group,
745 modest_msg_edit_priority_action_entries,
746 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
748 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
750 gtk_action_group_add_radio_actions (action_group,
751 modest_msg_edit_file_format_action_entries,
752 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
753 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
754 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
756 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
757 g_object_unref (action_group);
759 /* Load the UI definition */
760 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
763 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
764 g_clear_error (&error);
767 /* Add accelerators */
768 gtk_window_add_accel_group (GTK_WINDOW (obj),
769 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
771 parent_priv->menubar = NULL;
773 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
774 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
776 /* Note: This ModestPairList* must exist for as long as the picker
777 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
778 * so it can't know how to manage its memory. */
779 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
780 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
782 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
783 _("mail_va_from"), priv->from_field);
785 priv->to_field = modest_recpt_editor_new ();
786 priv->cc_field = modest_recpt_editor_new ();
787 priv->bcc_field = modest_recpt_editor_new ();
788 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
789 priv->priority_icon = gtk_image_new ();
790 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
791 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
792 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
793 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
794 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
795 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
796 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
797 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
798 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
799 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
800 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
801 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
802 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
803 add_attachment_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
804 gtk_alignment_set_padding (GTK_ALIGNMENT (add_attachment_align), 0, 0, MODEST_MARGIN_DEFAULT, 0);
805 gtk_container_add (GTK_CONTAINER (add_attachment_align), priv->add_attachment_button);
806 gtk_box_pack_start (GTK_BOX (priv->subject_box), add_attachment_align, FALSE, FALSE, 0);
807 priv->attachments_view = modest_attachments_view_new (NULL);
808 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
809 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
811 priv->header_box = gtk_vbox_new (FALSE, 0);
813 to_caption = modest_maemo_utils_create_captioned_with_size_type
814 (title_size_group, value_size_group,
815 _("mail_va_to"), FALSE, priv->to_field,
816 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
817 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
818 (title_size_group, value_size_group,
819 _("mail_va_cc"), FALSE, priv->cc_field,
820 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
821 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
822 (title_size_group, value_size_group,
823 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
824 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
825 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
826 _("mail_va_subject"), FALSE, priv->subject_box);
827 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
828 _("mail_va_attachment"),
830 priv->attachments_view,
831 HILDON_SIZE_AUTO_WIDTH |
832 HILDON_SIZE_AUTO_HEIGHT);
833 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
834 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
835 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
836 g_object_unref (title_size_group);
837 g_object_unref (value_size_group);
839 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
840 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
841 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
842 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
843 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
844 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
845 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
847 init_wp_text_view_style ();
849 priv->msg_body = modest_wp_text_view_new ();
852 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
853 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
854 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
855 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
856 #if (GTK_MINOR_VERSION >= 10)
857 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
858 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
860 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
861 deserialize_type, TRUE);
863 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
865 priv->find_toolbar = hildon_find_toolbar_new (NULL);
866 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
868 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
870 priv->pannable = hildon_pannable_area_new ();
872 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
873 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
874 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
876 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
877 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
878 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
880 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
881 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox),
882 hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable)));
883 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
885 window_box = gtk_vbox_new (FALSE, 0);
886 gtk_container_add (GTK_CONTAINER(obj), window_box);
888 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
890 /* Set window icon */
891 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
893 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
894 g_object_unref (window_icon);
899 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
901 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
903 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
904 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
905 priv->clipboard_change_handler_id))
906 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
907 priv->clipboard_change_handler_id);
908 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
909 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
910 priv->default_clipboard_change_handler_id))
911 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
912 priv->default_clipboard_change_handler_id);
914 if (priv->account_removed_handler_id &&
915 g_signal_handler_is_connected (modest_runtime_get_account_store (),
916 priv->account_removed_handler_id))
917 g_signal_handler_disconnect(modest_runtime_get_account_store (),
918 priv->account_removed_handler_id);
922 modest_msg_edit_window_finalize (GObject *obj)
924 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
926 /* Sanity check: shouldn't be needed, the window mgr should
927 call this function before */
928 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
930 if (priv->font_dialog != NULL) {
931 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
934 if (priv->clipboard_text != NULL) {
935 g_free (priv->clipboard_text);
936 priv->clipboard_text = NULL;
939 if (priv->draft_msg != NULL) {
940 TnyHeader *header = tny_msg_get_header (priv->draft_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->draft_msg);
946 priv->draft_msg = NULL;
948 if (priv->outbox_msg != NULL) {
949 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
950 if (TNY_IS_HEADER (header)) {
951 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
952 modest_window_mgr_unregister_header (mgr, header);
954 g_object_unref (priv->outbox_msg);
955 priv->outbox_msg = NULL;
957 if (priv->correct_scroll_idle > 0) {
958 g_source_remove (priv->correct_scroll_idle);
959 priv->correct_scroll_idle = 0;
961 if (priv->scroll_drag_timeout_id > 0) {
962 g_source_remove (priv->scroll_drag_timeout_id);
963 priv->scroll_drag_timeout_id = 0;
965 if (priv->clipboard_owner_idle > 0) {
966 g_source_remove (priv->clipboard_owner_idle);
967 priv->clipboard_owner_idle = 0;
969 if (priv->original_account_name)
970 g_free (priv->original_account_name);
971 g_free (priv->msg_uid);
972 g_free (priv->last_search);
973 g_object_unref (priv->faces_model);
974 g_object_unref (priv->sizes_model);
975 g_object_unref (priv->attachments);
976 g_object_unref (priv->images);
978 /* This had to stay alive for as long as the picker that used it: */
979 modest_pair_list_free (priv->from_field_protos);
981 G_OBJECT_CLASS(parent_class)->finalize (obj);
985 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
987 GdkPixbufLoader *loader;
993 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
995 if (loader == NULL) {
1001 tny_stream_reset (TNY_STREAM (stream));
1002 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1003 GError *error = NULL;
1004 unsigned char read_buffer[128];
1006 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1008 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1010 g_error_free (error);
1015 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1017 g_object_ref (pixbuf);
1018 gdk_pixbuf_loader_close (loader, NULL);
1019 g_object_unref (loader);
1024 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1025 GdkPixbuf *new_pixbuf;
1027 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1028 gdk_pixbuf_get_width (pixbuf);
1029 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1030 g_object_unref (pixbuf);
1031 pixbuf = new_pixbuf;
1035 *stream_size = size;
1041 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1043 ModestMsgEditWindowPrivate *priv;
1046 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1048 for (iter = tny_list_create_iterator (attachments);
1049 !tny_iterator_is_done (iter);
1050 tny_iterator_next (iter)) {
1051 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1052 const gchar *cid = tny_mime_part_get_content_id (part);
1053 const gchar *mime_type = tny_mime_part_get_content_type (part);
1054 if ((cid != NULL)&&(mime_type != NULL)) {
1055 guint64 stream_size;
1056 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1057 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1060 g_object_unref (stream);
1062 if (pixbuf != NULL) {
1063 priv->images_count ++;
1064 priv->images_size += stream_size;
1065 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1066 g_object_unref (pixbuf);
1069 g_object_unref (part);
1071 g_object_unref (iter);
1075 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1077 TnyMimePart *parent = NULL;
1078 const gchar *content_type = NULL;
1079 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1081 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1083 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1084 parent = g_object_ref (msg);
1085 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1086 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1089 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1090 iter = tny_list_create_iterator (parts);
1091 while (!tny_iterator_is_done (iter)) {
1093 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1094 content_type = tny_mime_part_get_content_type (part);
1095 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1099 g_object_unref (part);
1101 tny_iterator_next (iter);
1103 g_object_unref (iter);
1104 g_object_unref (parts);
1107 if (parent != NULL) {
1108 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1111 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1112 iter = tny_list_create_iterator (parts);
1113 while (!tny_iterator_is_done (iter)) {
1115 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1116 content_type = tny_mime_part_get_content_type (part);
1117 if (content_type && g_str_has_prefix (content_type, "image/")) {
1118 tny_list_prepend (priv->images, (GObject *) part);
1120 g_object_unref (part);
1121 tny_iterator_next (iter);
1123 g_object_unref (iter);
1124 g_object_unref (parts);
1125 g_object_unref (parent);
1130 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1133 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1135 for (iter = tny_list_create_iterator (attachments) ;
1136 !tny_iterator_is_done (iter);
1137 tny_iterator_next (iter)) {
1138 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1139 const gchar *cid = tny_mime_part_get_content_id (part);
1141 char *invalid = NULL;
1142 gint int_cid = strtol (cid, &invalid, 10);
1143 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1144 priv->next_cid = int_cid + 1;
1147 g_object_unref (part);
1149 g_object_unref (iter);
1153 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1156 gchar *to, *cc, *bcc, *subject;
1158 ModestMsgEditWindowPrivate *priv;
1159 ModestWindowPrivate *parent_priv;
1161 TnyHeaderFlags priority_flags;
1162 TnyFolder *msg_folder;
1163 gboolean is_html = FALSE;
1164 gboolean field_view_set;
1166 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1167 g_return_if_fail (TNY_IS_MSG (msg));
1169 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1170 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1172 header = tny_msg_get_header (msg);
1173 to = tny_header_dup_to (header);
1174 cc = tny_header_dup_cc (header);
1175 bcc = tny_header_dup_bcc (header);
1176 subject = tny_header_dup_subject (header);
1177 priority_flags = tny_header_get_priority (header);
1180 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1182 field_view_set = TRUE;
1184 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1185 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1186 gtk_widget_show (priv->cc_caption);
1187 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1188 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1189 gtk_widget_hide (priv->cc_caption);
1190 field_view_set = FALSE;
1192 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1194 field_view_set = TRUE;
1196 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1197 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1198 gtk_widget_show (priv->bcc_caption);
1199 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1200 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1201 gtk_widget_hide (priv->bcc_caption);
1202 field_view_set = FALSE;
1204 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1208 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1209 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1212 update_window_title (self);
1214 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1215 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1217 if ((body == NULL)||(body[0] == '\0')) {
1219 body = modest_text_utils_convert_to_html ("");
1222 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1223 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1226 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1229 /* Add attachments to the view */
1230 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1231 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1232 if (tny_list_get_length (priv->attachments) == 0) {
1233 gtk_widget_hide (priv->attachments_caption);
1235 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1236 gtk_widget_show_all (priv->attachments_caption);
1238 get_related_images (self, msg);
1239 update_next_cid (self, priv->attachments);
1240 update_next_cid (self, priv->images);
1241 replace_with_images (self, priv->images);
1243 if (preserve_is_rich && !is_html) {
1244 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1245 /* Get the default format required from configuration */
1246 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1247 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1250 /* Set the default focus depending on having already a To: field or not */
1251 if ((!to)||(*to == '\0')) {
1252 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1254 gtk_widget_grab_focus (priv->msg_body);
1257 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1259 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1260 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1262 modest_msg_edit_window_set_modified (self, FALSE);
1264 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1265 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1266 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1267 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1269 if (priv->msg_uid) {
1270 g_free (priv->msg_uid);
1271 priv->msg_uid = NULL;
1274 /* we should set a reference to the incoming message if it is a draft */
1275 msg_folder = tny_msg_get_folder (msg);
1277 if (modest_tny_folder_is_local_folder (msg_folder)) {
1278 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1279 if (type == TNY_FOLDER_TYPE_INVALID)
1280 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1282 if (type == TNY_FOLDER_TYPE_DRAFTS)
1283 priv->draft_msg = g_object_ref(msg);
1284 if (type == TNY_FOLDER_TYPE_OUTBOX)
1285 priv->outbox_msg = g_object_ref(msg);
1286 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1288 g_object_unref (msg_folder);
1299 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1301 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1302 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1303 GtkWidget *placeholder;
1304 GtkWidget *tool_item;
1309 GtkWidget *sizes_menu;
1310 GtkWidget *fonts_menu;
1315 ldots_len = g_unichar_to_utf8 (0x2026, ldots);
1316 ldots[ldots_len] = '\0';
1319 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1320 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1321 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1322 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1324 /* Font color placeholder */
1325 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1326 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1329 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1330 priv->font_color_button = hildon_color_button_new ();
1331 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1332 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1333 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1334 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1335 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1336 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1337 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1338 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1340 G_CALLBACK (modest_msg_edit_window_color_button_change),
1343 /* Font size and face placeholder */
1344 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1345 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1347 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1348 priv->size_tool_button_label = gtk_label_new (NULL);
1349 hildon_helper_set_logical_color (GTK_WIDGET (priv->size_tool_button_label), GTK_RC_TEXT,
1350 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1351 hildon_helper_set_logical_color (GTK_WIDGET (priv->size_tool_button_label), GTK_RC_FG,
1352 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1353 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1354 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1355 size_text, ldots, "</span>", NULL);
1356 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1358 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1359 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1360 sizes_menu = gtk_menu_new ();
1361 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1362 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1365 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1366 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1368 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1372 if (wp_font_size[size_index] == 12)
1373 priv->current_size_index = size_index;
1377 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1378 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1379 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1380 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1381 priv->font_size_toolitem = tool_item;
1384 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1385 priv->font_tool_button_label = gtk_label_new (NULL);
1386 hildon_helper_set_logical_color (GTK_WIDGET (priv->font_tool_button_label), GTK_RC_TEXT,
1387 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1388 hildon_helper_set_logical_color (GTK_WIDGET (priv->font_tool_button_label), GTK_RC_FG,
1389 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1390 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt",ldots,"</span>", NULL);
1391 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1393 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1394 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1395 fonts_menu = gtk_menu_new ();
1396 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1397 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1400 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1402 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1403 0, wp_get_font_name (font_index),
1406 if (font_index == DEFAULT_FONT)
1407 priv->current_face_index = font_index;
1409 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1410 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1411 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1412 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1413 priv->font_face_toolitem = tool_item;
1415 /* Set expand and homogeneous for remaining items */
1416 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1417 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1418 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1419 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1420 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1421 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1422 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1423 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1424 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1426 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1427 will not show the tool items added to the placeholders) */
1428 gtk_widget_show_all (parent_priv->toolbar);
1430 /* Set the no show all *after* showing all items. We do not
1431 want the toolbar to be shown with a show all because it
1432 could go agains the gconf setting regarding showing or not
1433 the toolbar of the editor window */
1434 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1440 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1443 ModestWindowPrivate *parent_priv;
1444 ModestMsgEditWindowPrivate *priv;
1445 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1446 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1447 ModestWindowMgr *mgr = NULL;
1449 g_return_val_if_fail (msg, NULL);
1450 g_return_val_if_fail (account_name, NULL);
1452 mgr = modest_runtime_get_window_mgr ();
1454 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1456 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1457 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1459 /* Menubar. Update the state of some toggles */
1460 priv->from_field_protos = get_transports ();
1461 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1462 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1463 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1464 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1466 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1467 hildon_touch_selector_get_current_text
1468 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1469 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1470 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1473 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1475 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1477 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1479 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1481 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1482 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1483 /* Add common dimming rules */
1484 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1485 modest_msg_edit_window_toolbar_dimming_entries,
1486 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1487 MODEST_WINDOW (obj));
1488 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1489 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1490 MODEST_WINDOW (obj));
1491 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1492 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1493 MODEST_WINDOW (obj));
1494 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1495 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1496 MODEST_WINDOW (obj));
1497 /* Insert dimming rules group for this window */
1498 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1499 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1501 /* Setup app menu */
1502 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1504 /* Checks the dimming rules */
1505 g_object_unref (toolbar_rules_group);
1506 g_object_unref (clipboard_rules_group);
1507 gtk_widget_hide (priv->priority_icon);
1508 gtk_widget_queue_resize (priv->subject_box);
1509 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1511 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1513 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1514 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1515 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1516 priv->update_caption_visibility = TRUE;
1518 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1520 /* Track account-removed signal, this window should be closed
1521 in the case we're creating a mail associated to the account
1523 priv->account_removed_handler_id =
1524 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1526 G_CALLBACK(on_account_removed),
1529 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1531 return (ModestWindow*) obj;
1535 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1537 GString **string_buffer = (GString **) user_data;
1539 *string_buffer = g_string_append (*string_buffer, buffer);
1545 * @result: A new string which should be freed with g_free().
1548 get_formatted_data (ModestMsgEditWindow *edit_window)
1550 ModestMsgEditWindowPrivate *priv;
1551 GString *string_buffer = g_string_new ("");
1553 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1555 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1557 modest_text_utils_hyperlinkify (string_buffer);
1559 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1561 return g_string_free (string_buffer, FALSE);
1566 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1569 const gchar *account_name;
1570 ModestMsgEditWindowPrivate *priv;
1571 TnyIterator *att_iter;
1573 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1575 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1577 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1578 g_return_val_if_fail (account_name, NULL);
1581 /* don't free these (except from) */
1582 data = g_slice_new0 (MsgData);
1583 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1585 data->account_name = g_strdup (account_name);
1586 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1587 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1588 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1589 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1590 if (priv->draft_msg) {
1591 data->draft_msg = g_object_ref (priv->draft_msg);
1592 } else if (priv->outbox_msg) {
1593 data->draft_msg = g_object_ref (priv->outbox_msg);
1595 data->draft_msg = NULL;
1598 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1600 gtk_text_buffer_get_bounds (buf, &b, &e);
1601 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1603 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1604 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1606 data->html_body = NULL;
1608 /* deep-copy the data */
1609 att_iter = tny_list_create_iterator (priv->attachments);
1610 data->attachments = NULL;
1611 while (!tny_iterator_is_done (att_iter)) {
1612 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1613 if (!(TNY_IS_MIME_PART(part))) {
1614 g_warning ("strange data in attachment list");
1615 g_object_unref (part);
1616 tny_iterator_next (att_iter);
1619 data->attachments = g_list_append (data->attachments,
1621 tny_iterator_next (att_iter);
1623 g_object_unref (att_iter);
1625 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1626 att_iter = tny_list_create_iterator (priv->images);
1627 data->images = NULL;
1628 while (!tny_iterator_is_done (att_iter)) {
1629 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1631 if (!(TNY_IS_MIME_PART(part))) {
1632 g_warning ("strange data in attachment list");
1633 g_object_unref (part);
1634 tny_iterator_next (att_iter);
1637 cid = tny_mime_part_get_content_id (part);
1639 gchar *image_tag_id;
1640 GtkTextTag *image_tag;
1642 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1643 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1644 g_free (image_tag_id);
1646 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1648 ((gtk_text_iter_has_tag (&iter, image_tag))||
1649 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1650 data->images = g_list_append (data->images,
1651 g_object_ref (part));
1653 g_object_unref (part);
1654 tny_iterator_next (att_iter);
1656 g_object_unref (att_iter);
1658 data->priority_flags = priv->priority_flags;
1665 unref_gobject (GObject *obj, gpointer data)
1667 if (!G_IS_OBJECT(obj))
1669 g_object_unref (obj);
1673 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1676 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1684 g_free (data->from);
1685 g_free (data->subject);
1686 g_free (data->plain_body);
1687 g_free (data->html_body);
1688 g_free (data->account_name);
1690 if (data->draft_msg != NULL) {
1691 g_object_unref (data->draft_msg);
1692 data->draft_msg = NULL;
1695 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1696 g_list_free (data->attachments);
1697 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1698 g_list_free (data->images);
1700 g_slice_free (MsgData, data);
1704 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1706 guint64 *parts_size)
1708 ModestMsgEditWindowPrivate *priv;
1710 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1712 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1714 /* TODO: add images */
1715 *parts_size += priv->images_size;
1716 *parts_count += priv->images_count;
1721 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1724 ModestMsgEditWindowPrivate *priv = NULL;
1725 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1727 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1729 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1731 return MODEST_MSG_EDIT_FORMAT_HTML;
1733 return MODEST_MSG_EDIT_FORMAT_TEXT;
1737 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1738 ModestMsgEditFormat format)
1740 ModestMsgEditWindowPrivate *priv;
1742 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1743 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1746 case MODEST_MSG_EDIT_FORMAT_HTML:
1747 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1749 case MODEST_MSG_EDIT_FORMAT_TEXT:
1750 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1753 g_return_if_reached ();
1757 ModestMsgEditFormatState *
1758 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1760 ModestMsgEditFormatState *format_state = NULL;
1761 ModestMsgEditWindowPrivate *priv;
1762 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1764 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1765 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1767 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1769 format_state = g_new0 (ModestMsgEditFormatState, 1);
1770 format_state->bold = buffer_format->bold&0x1;
1771 format_state->italics = buffer_format->italic&0x1;
1772 format_state->bullet = buffer_format->bullet&0x1;
1773 format_state->color = buffer_format->color;
1774 format_state->font_size = buffer_format->font_size;
1775 format_state->font_family = wp_get_font_name (buffer_format->font);
1776 format_state->justification = buffer_format->justification;
1777 g_free (buffer_format);
1779 return format_state;
1784 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1785 const ModestMsgEditFormatState *format_state)
1787 ModestMsgEditWindowPrivate *priv;
1788 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1789 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1790 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1791 g_return_if_fail (format_state != NULL);
1793 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1794 gtk_widget_grab_focus (priv->msg_body);
1795 buffer_format->bold = (format_state->bold != FALSE);
1796 buffer_format->italic = (format_state->italics != FALSE);
1797 buffer_format->color = format_state->color;
1798 buffer_format->font_size = format_state->font_size;
1799 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1800 buffer_format->justification = format_state->justification;
1801 buffer_format->bullet = format_state->bullet;
1803 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1805 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1806 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1807 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1808 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1809 buffer_format->cs.font = (buffer_format->font != current_format->font);
1810 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1811 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1813 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1814 if (buffer_format->cs.bold) {
1815 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1816 GINT_TO_POINTER (buffer_format->bold&0x1));
1818 if (buffer_format->cs.italic) {
1819 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1820 GINT_TO_POINTER (buffer_format->italic&0x1));
1822 if (buffer_format->cs.color) {
1823 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1824 GINT_TO_POINTER (&(buffer_format->color)));
1826 if (buffer_format->cs.font_size) {
1827 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1828 GINT_TO_POINTER (buffer_format->font_size));
1830 if (buffer_format->cs.justification) {
1831 switch (buffer_format->justification) {
1832 case GTK_JUSTIFY_LEFT:
1833 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1834 GINT_TO_POINTER(TRUE));
1836 case GTK_JUSTIFY_CENTER:
1837 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1838 GINT_TO_POINTER(TRUE));
1840 case GTK_JUSTIFY_RIGHT:
1841 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1842 GINT_TO_POINTER(TRUE));
1849 if (buffer_format->cs.font) {
1850 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1851 GINT_TO_POINTER (buffer_format->font));
1853 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1854 if (buffer_format->cs.bullet) {
1855 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1856 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1858 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1860 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1862 g_free (buffer_format);
1863 g_free (current_format);
1865 /* Check dimming rules */
1866 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1867 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1871 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1873 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1875 ModestWindowPrivate *parent_priv;
1876 ModestMsgEditWindowPrivate *priv;
1880 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1881 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1883 ldots_len = g_unichar_to_utf8 (0x2026, ldots);
1884 ldots[ldots_len] = '\0';
1886 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1887 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1888 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1889 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1891 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1892 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1893 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1896 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1898 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1899 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1901 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1902 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1904 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1905 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1908 switch (buffer_format->justification)
1910 case GTK_JUSTIFY_LEFT:
1911 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1913 case GTK_JUSTIFY_CENTER:
1914 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1916 case GTK_JUSTIFY_RIGHT:
1917 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1924 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1926 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1927 G_CALLBACK (modest_msg_edit_window_color_button_change),
1929 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1930 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1931 G_CALLBACK (modest_msg_edit_window_color_button_change),
1934 if (priv->current_size_index != buffer_format->font_size) {
1938 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
1939 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
1943 priv->current_size_index = buffer_format->font_size;
1945 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
1946 markup = g_strconcat ("<span font_family='Sans'>",
1947 size_text, ldots, "</span>", NULL);
1949 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1953 gtk_tree_path_free (path);
1956 if (priv->current_face_index != buffer_format->font) {
1960 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
1961 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
1965 priv->current_face_index = buffer_format->font;
1966 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
1967 markup = g_strconcat ("<span font_family='", face_name, "'>Tt", ldots, "</span>", NULL);
1968 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1975 g_free (buffer_format);
1979 #ifdef MODEST_HILDON_VERSION_0
1981 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1984 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1985 ModestMsgEditWindowPrivate *priv;
1986 GtkWidget *dialog = NULL;
1988 GdkColor *new_color = NULL;
1990 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1991 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1993 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1994 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1995 g_free (buffer_format);
1997 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
1998 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1999 if (new_color != NULL) {
2000 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2001 (gpointer) new_color);
2004 gtk_widget_destroy (dialog);
2009 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2012 ModestMsgEditWindowPrivate *priv;
2013 GtkWidget *dialog = NULL;
2015 GdkColor *old_color = NULL;
2016 const GdkColor *new_color = NULL;
2018 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2019 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2021 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2022 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2024 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2025 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2026 if (new_color != NULL)
2027 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2029 gtk_widget_destroy (dialog);
2035 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2038 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2039 ModestMsgEditWindowPrivate *priv;
2040 GtkWidget *dialog = NULL;
2042 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2043 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2045 dialog = hildon_color_chooser_new ();
2046 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2047 g_free (buffer_format);
2049 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2051 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2052 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2055 gtk_widget_destroy (dialog);
2060 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2063 ModestMsgEditWindowPrivate *priv;
2064 GtkWidget *dialog = NULL;
2065 GdkColor *old_color = NULL;
2067 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2068 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2070 dialog = hildon_color_chooser_new ();
2071 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2073 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2075 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2076 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2078 gtk_widget_destroy (dialog);
2081 #endif /*!MODEST_HILDON_VERSION_0*/
2086 create_stream_for_uri (const gchar* uri)
2091 TnyStream *result = NULL;
2093 GnomeVFSHandle *handle = NULL;
2094 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2095 if (test == GNOME_VFS_OK) {
2096 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2097 /* Streams over OBEX (Bluetooth) are not seekable but
2098 * we expect them to be (we might need to read them
2099 * several times). So if this is a Bluetooth URI just
2100 * read the whole file into memory (this is not a fast
2101 * protocol so we can assume that these files are not
2102 * going to be very big) */
2103 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2104 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2105 TnyStream *memstream = tny_camel_mem_stream_new ();
2106 tny_stream_write_to_stream (vfssstream, memstream);
2107 g_object_unref (vfssstream);
2110 result = vfssstream;
2118 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2121 ModestMsgEditWindowPrivate *priv;
2122 GtkWidget *dialog = NULL;
2124 GSList *uris = NULL;
2125 GSList *uri_node = NULL;
2127 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2129 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2130 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2131 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2133 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2135 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2136 GTK_WINDOW (dialog), GTK_WINDOW (window));
2138 response = gtk_dialog_run (GTK_DIALOG (dialog));
2140 case GTK_RESPONSE_OK:
2141 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2146 gtk_widget_destroy (dialog);
2148 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2150 GnomeVFSHandle *handle = NULL;
2151 GnomeVFSResult result;
2152 GtkTextIter position;
2153 GtkTextMark *insert_mark;
2155 uri = (const gchar *) uri_node->data;
2156 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2157 if (result == GNOME_VFS_OK) {
2159 GnomeVFSFileInfo *info;
2160 gchar *filename, *basename, *escaped_filename;
2161 TnyMimePart *mime_part;
2163 const gchar *mime_type = NULL;
2164 GnomeVFSURI *vfs_uri;
2165 guint64 stream_size;
2167 gnome_vfs_close (handle);
2168 vfs_uri = gnome_vfs_uri_new (uri);
2170 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2171 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2172 g_free (escaped_filename);
2173 gnome_vfs_uri_unref (vfs_uri);
2174 info = gnome_vfs_file_info_new ();
2176 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2177 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2179 mime_type = gnome_vfs_file_info_get_mime_type (info);
2181 mime_part = tny_platform_factory_new_mime_part
2182 (modest_runtime_get_platform_factory ());
2184 TnyStream *stream = create_stream_for_uri (uri);
2186 if (stream == NULL) {
2188 modest_platform_information_banner (NULL, NULL,
2189 _FM("sfil_ib_opening_not_allowed"));
2191 g_object_unref (mime_part);
2192 gnome_vfs_file_info_unref (info);
2196 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2198 content_id = g_strdup_printf ("%d", priv->next_cid);
2199 tny_mime_part_set_content_id (mime_part, content_id);
2200 g_free (content_id);
2203 basename = g_path_get_basename (filename);
2204 tny_mime_part_set_filename (mime_part, basename);
2207 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2209 if (pixbuf != NULL) {
2210 priv->images_size += stream_size;
2211 priv->images_count ++;
2212 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2213 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2214 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2215 g_object_unref (pixbuf);
2218 tny_list_prepend (priv->images, (GObject *) mime_part);
2219 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2221 g_object_unref (mime_part);
2222 gnome_vfs_file_info_unref (info);
2231 on_attach_file_response (GtkDialog *dialog,
2235 GSList *uris = NULL;
2237 GnomeVFSFileSize total_size, allowed_size;
2238 ModestMsgEditWindow *window;
2239 ModestMsgEditWindowPrivate *priv;
2244 case GTK_RESPONSE_OK:
2245 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2251 window = MODEST_MSG_EDIT_WINDOW (user_data);
2252 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2254 /* allowed size is the maximum size - what's already there */
2255 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2256 &att_num, &att_size);
2257 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2260 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2262 const gchar *uri = (const gchar *) uri_node->data;
2265 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2267 if (total_size > allowed_size) {
2268 g_warning ("%s: total size: %u",
2269 __FUNCTION__, (unsigned int)total_size);
2272 allowed_size -= total_size;
2274 g_slist_foreach (uris, (GFunc) g_free, NULL);
2275 g_slist_free (uris);
2277 gtk_widget_destroy (GTK_WIDGET (dialog));
2281 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2283 GtkWidget *dialog = NULL;
2284 ModestMsgEditWindowPrivate *priv;
2286 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2288 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2290 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2293 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2294 GTK_FILE_CHOOSER_ACTION_OPEN);
2295 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2296 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2297 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2298 GTK_WINDOW (dialog), GTK_WINDOW (window));
2300 /* Connect to response & show */
2301 g_signal_connect (dialog, "response",
2302 G_CALLBACK (on_attach_file_response), window);
2303 gtk_widget_show (dialog);
2308 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2310 GnomeVFSFileSize allowed_size)
2313 GnomeVFSHandle *handle = NULL;
2314 ModestMsgEditWindowPrivate *priv;
2315 GnomeVFSResult result;
2316 GnomeVFSFileSize size = 0;
2317 g_return_val_if_fail (window, 0);
2318 g_return_val_if_fail (uri, 0);
2320 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2322 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2323 if (result == GNOME_VFS_OK) {
2324 TnyMimePart *mime_part;
2326 const gchar *mime_type = NULL;
2328 gchar *escaped_filename;
2331 GnomeVFSFileInfo *info;
2332 GnomeVFSURI *vfs_uri;
2334 gnome_vfs_close (handle);
2335 vfs_uri = gnome_vfs_uri_new (uri);
2338 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2339 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2340 g_free (escaped_filename);
2341 gnome_vfs_uri_unref (vfs_uri);
2343 info = gnome_vfs_file_info_new ();
2345 if (gnome_vfs_get_file_info (uri,
2347 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2349 mime_type = gnome_vfs_file_info_get_mime_type (info);
2350 mime_part = tny_platform_factory_new_mime_part
2351 (modest_runtime_get_platform_factory ());
2353 /* try to get the attachment's size; this may fail for weird
2354 * file systems, like obex, upnp... */
2355 if (allowed_size != 0 &&
2356 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2358 if (size > allowed_size) {
2359 modest_platform_information_banner (NULL, NULL,
2360 _FM("sfil_ib_opening_not_allowed"));
2364 g_warning ("%s: could not get attachment size", __FUNCTION__);
2366 stream = create_stream_for_uri (uri);
2368 if (stream == NULL) {
2370 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2372 g_object_unref (mime_part);
2373 gnome_vfs_file_info_unref (info);
2377 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2378 g_object_unref (stream);
2380 content_id = g_strdup_printf ("%d", priv->next_cid);
2381 tny_mime_part_set_content_id (mime_part, content_id);
2382 g_free (content_id);
2385 basename = g_path_get_basename (filename);
2386 tny_mime_part_set_filename (mime_part, basename);
2389 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2390 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2392 info->size == 0, info->size);
2393 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2394 gtk_widget_show_all (priv->attachments_caption);
2395 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2397 g_object_unref (mime_part);
2398 gnome_vfs_file_info_unref (info);
2405 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2408 ModestMsgEditWindowPrivate *priv;
2411 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2412 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2414 if (att_list == NULL) {
2415 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2416 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2417 g_object_unref (att_list);
2422 g_object_ref (att_list);
2425 if (tny_list_get_length (att_list) == 0) {
2426 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2428 gboolean dialog_response;
2429 gchar *message = NULL;
2430 gchar *filename = NULL;
2432 if (tny_list_get_length (att_list) == 1) {
2434 iter = tny_list_create_iterator (att_list);
2435 part = (TnyMimePart *) tny_iterator_get_current (iter);
2436 g_object_unref (iter);
2437 if (TNY_IS_MSG (part)) {
2438 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2440 filename = tny_header_dup_subject (header);
2441 g_object_unref (header);
2443 if (filename == NULL) {
2444 filename = g_strdup (_("mail_va_no_subject"));
2447 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2449 g_object_unref (part);
2451 filename = g_strdup ("");
2453 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2454 "emev_nc_delete_attachments",
2455 tny_list_get_length (att_list)), filename);
2458 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2462 if (dialog_response != GTK_RESPONSE_OK) {
2463 g_object_unref (att_list);
2467 for (iter = tny_list_create_iterator (att_list);
2468 !tny_iterator_is_done (iter);
2469 tny_iterator_next (iter)) {
2470 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2471 const gchar *att_id;
2472 tny_list_remove (priv->attachments, (GObject *) mime_part);
2474 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2476 if (tny_list_get_length (priv->attachments) == 0)
2477 gtk_widget_hide (priv->attachments_caption);
2478 att_id = tny_mime_part_get_content_id (mime_part);
2480 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2482 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2483 g_object_unref (mime_part);
2485 g_object_unref (iter);
2488 g_object_unref (att_list);
2490 /* if the last attachment has been removed, focus the Subject: field */
2491 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2492 gtk_widget_grab_focus (priv->subject_field);
2496 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2499 ModestMsgEditWindowPrivate *priv;
2500 GdkColor *new_color;
2501 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2503 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2504 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2507 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2509 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2511 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2513 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2518 font_size_clicked (GtkToolButton *button,
2519 ModestMsgEditWindow *window)
2521 ModestMsgEditWindowPrivate *priv;
2522 GtkWidget *selector, *dialog;
2524 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2526 selector = hildon_touch_selector_new ();
2527 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2528 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2530 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2531 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2533 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2537 WPTextBufferFormat format;
2541 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2543 memset (&format, 0, sizeof (format));
2544 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2546 format.cs.font_size = TRUE;
2547 format.cs.text_position = TRUE;
2548 format.cs.font = TRUE;
2549 format.font_size = new_index;
2550 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2552 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2553 GINT_TO_POINTER (new_index)))
2554 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2556 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2557 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2558 ldots_len = g_unichar_to_utf8 (0x2026, ldots);
2559 ldots[ldots_len] = '\0';
2560 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2561 size_text, ldots, "</span>", NULL);
2563 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2567 gtk_widget_destroy (dialog);
2569 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2574 font_face_clicked (GtkToolButton *button,
2575 ModestMsgEditWindow *window)
2577 ModestMsgEditWindowPrivate *priv;
2578 GtkWidget *selector, *dialog;
2579 GtkCellRenderer *renderer;
2581 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2583 selector = hildon_touch_selector_new ();
2584 renderer = gtk_cell_renderer_text_new ();
2585 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2586 renderer, "family", 0, "text", 0, NULL);
2587 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2589 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2590 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2592 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2593 gint new_font_index;
2597 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2598 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2599 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2605 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2607 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2608 GINT_TO_POINTER(new_font_index)))
2609 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2611 ldots_len = g_unichar_to_utf8 (0x2026, ldots);
2612 ldots[ldots_len] = '\0';
2613 markup = g_strconcat ("<span font_family='", face_name, "'>Tt", ldots, "</span>", NULL);
2614 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2616 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2620 gtk_tree_path_free (path);
2623 gtk_widget_destroy (dialog);
2625 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2630 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2633 ModestMsgEditWindowPrivate *priv = NULL;
2634 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2636 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2637 if (!priv->update_caption_visibility)
2640 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2642 gtk_widget_show (priv->cc_caption);
2644 gtk_widget_hide (priv->cc_caption);
2646 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2650 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2653 ModestMsgEditWindowPrivate *priv = NULL;
2654 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2656 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2657 if (!priv->update_caption_visibility)
2660 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2662 gtk_widget_show (priv->bcc_caption);
2664 gtk_widget_hide (priv->bcc_caption);
2666 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2670 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2671 ModestRecptEditor *editor)
2673 ModestMsgEditWindowPrivate *priv;
2675 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2676 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2678 /* we check for low-mem; in that case, show a warning, and don't allow
2679 * for the addressbook
2681 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2684 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2686 if (editor == NULL) {
2687 GtkWidget *view_focus;
2688 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2690 /* This code should be kept in sync with ModestRecptEditor. The
2691 textview inside the recpt editor is the one that really gets the
2692 focus. As it's inside a scrolled window, and this one inside the
2693 hbox recpt editor inherits from, we'll need to go up in the
2694 hierarchy to know if the text view is part of the recpt editor
2695 or if it's a different text entry */
2697 if (gtk_widget_get_parent (view_focus)) {
2698 GtkWidget *first_parent;
2700 first_parent = gtk_widget_get_parent (view_focus);
2701 if (gtk_widget_get_parent (first_parent) &&
2702 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2703 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2708 editor = MODEST_RECPT_EDITOR (priv->to_field);
2712 modest_address_book_select_addresses (editor);
2717 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2719 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2721 modest_msg_edit_window_open_addressbook (window, NULL);
2725 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2726 gboolean show_toolbar)
2728 ModestWindowPrivate *parent_priv;
2730 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2731 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2733 /* We can not just use the code of
2734 modest_msg_edit_window_setup_toolbar because it has a
2735 mixture of both initialization and creation code. */
2737 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2739 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2743 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2744 TnyHeaderFlags priority_flags)
2746 ModestMsgEditWindowPrivate *priv;
2747 ModestWindowPrivate *parent_priv;
2749 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2751 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2752 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2754 if (priv->priority_flags != priority_flags) {
2755 GtkAction *priority_action = NULL;
2757 priv->priority_flags = priority_flags;
2759 switch (priority_flags) {
2760 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2761 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2762 MODEST_HEADER_ICON_HIGH,
2763 HILDON_ICON_SIZE_SMALL);
2764 gtk_widget_show (priv->priority_icon);
2765 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2766 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2768 case TNY_HEADER_FLAG_LOW_PRIORITY:
2769 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2770 MODEST_HEADER_ICON_LOW,
2771 HILDON_ICON_SIZE_SMALL);
2772 gtk_widget_show (priv->priority_icon);
2773 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2774 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2777 gtk_widget_hide (priv->priority_icon);
2778 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2779 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2782 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2783 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2785 gtk_widget_queue_resize (priv->subject_box);
2789 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2792 ModestMsgEditWindowPrivate *priv;
2793 ModestWindowPrivate *parent_priv;
2794 gint current_format;
2796 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2798 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2799 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2801 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2802 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2804 if (current_format != file_format) {
2805 switch (file_format) {
2806 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2807 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2808 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2810 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2814 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2815 response = gtk_dialog_run (GTK_DIALOG (dialog));
2816 gtk_widget_destroy (dialog);
2817 if (response == GTK_RESPONSE_OK) {
2818 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2820 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2821 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2826 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2827 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2828 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2833 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2836 ModestMsgEditWindowPrivate *priv;
2837 WPTextBufferFormat oldfmt, fmt;
2838 gint old_position = 0;
2842 GdkColor *color = NULL;
2843 gboolean bold, bold_set, italic, italic_set;
2844 gboolean underline, underline_set;
2845 gboolean strikethrough, strikethrough_set;
2846 gboolean position_set;
2847 gboolean font_size_set, font_set, color_set;
2850 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2851 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2853 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2854 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2855 GTK_WINDOW(dialog), GTK_WINDOW (window));
2857 /* First we get the currently selected font information */
2858 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2860 switch (oldfmt.text_position) {
2861 case TEXT_POSITION_NORMAL:
2864 case TEXT_POSITION_SUPERSCRIPT:
2872 g_object_set (G_OBJECT (dialog),
2873 "bold", oldfmt.bold != FALSE,
2874 "bold-set", !oldfmt.cs.bold,
2875 "underline", oldfmt.underline != FALSE,
2876 "underline-set", !oldfmt.cs.underline,
2877 "italic", oldfmt.italic != FALSE,
2878 "italic-set", !oldfmt.cs.italic,
2879 "strikethrough", oldfmt.strikethrough != FALSE,
2880 "strikethrough-set", !oldfmt.cs.strikethrough,
2881 "color", &oldfmt.color,
2882 "color-set", !oldfmt.cs.color,
2883 "size", wp_font_size[oldfmt.font_size],
2884 "size-set", !oldfmt.cs.font_size,
2885 "position", old_position,
2886 "position-set", !oldfmt.cs.text_position,
2887 "family", wp_get_font_name (oldfmt.font),
2888 "family-set", !oldfmt.cs.font,
2891 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2892 GTK_WINDOW (dialog), GTK_WINDOW (window));
2893 gtk_widget_show_all (dialog);
2894 priv->font_dialog = dialog;
2895 response = gtk_dialog_run (GTK_DIALOG (dialog));
2896 priv->font_dialog = NULL;
2897 if (response == GTK_RESPONSE_OK) {
2899 g_object_get( dialog,
2901 "bold-set", &bold_set,
2902 "underline", &underline,
2903 "underline-set", &underline_set,
2905 "italic-set", &italic_set,
2906 "strikethrough", &strikethrough,
2907 "strikethrough-set", &strikethrough_set,
2909 "color-set", &color_set,
2911 "size-set", &font_size_set,
2912 "family", &font_name,
2913 "family-set", &font_set,
2914 "position", &position,
2915 "position-set", &position_set,
2920 if (response == GTK_RESPONSE_OK) {
2921 memset(&fmt, 0, sizeof(fmt));
2927 fmt.italic = italic;
2928 fmt.cs.italic = TRUE;
2930 if (underline_set) {
2931 fmt.underline = underline;
2932 fmt.cs.underline = TRUE;
2934 if (strikethrough_set) {
2935 fmt.strikethrough = strikethrough;
2936 fmt.cs.strikethrough = TRUE;
2941 ? TEXT_POSITION_NORMAL
2942 : ( ( position == 1 )
2943 ? TEXT_POSITION_SUPERSCRIPT
2944 : TEXT_POSITION_SUBSCRIPT );
2945 fmt.cs.text_position = TRUE;
2946 fmt.font_size = oldfmt.font_size;
2950 fmt.cs.color = TRUE;
2953 fmt.font = wp_get_font_index(font_name,
2958 if (font_size_set) {
2959 fmt.cs.font_size = TRUE;
2960 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2962 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2963 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2965 gtk_widget_destroy (dialog);
2967 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2971 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2973 ModestMsgEditWindowPrivate *priv;
2975 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2976 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2978 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2980 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2981 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2985 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2987 ModestMsgEditWindowPrivate *priv;
2989 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2990 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2992 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2994 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2995 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3000 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3002 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3004 priv->can_undo = can_undo;
3008 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3010 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3012 priv->can_redo = can_redo;
3016 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3018 ModestMsgEditWindowPrivate *priv;
3019 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3020 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3022 return priv->can_undo;
3026 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3028 ModestMsgEditWindowPrivate *priv;
3029 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3030 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3032 return priv->can_redo;
3037 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3040 GtkTextIter match_start, match_end;
3042 if (image_id == NULL)
3045 gtk_text_buffer_get_start_iter (buffer, &iter);
3047 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3048 GSList *tags = gtk_text_iter_get_tags (&match_start);
3050 for (node = tags; node != NULL; node = g_slist_next (node)) {
3051 GtkTextTag *tag = (GtkTextTag *) node->data;
3052 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3053 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3054 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3056 offset = gtk_text_iter_get_offset (&match_start);
3057 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3058 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3062 gtk_text_iter_forward_char (&iter);
3067 message_is_empty (ModestMsgEditWindow *window)
3069 ModestMsgEditWindowPrivate *priv = NULL;
3071 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3072 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3074 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3075 * so we can ignore markup.
3077 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3080 count = gtk_text_buffer_get_char_count (buf);
3086 msg_body_focus (GtkWidget *focus,
3087 GdkEventFocus *event,
3091 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3092 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3093 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3098 recpt_field_changed (GtkTextBuffer *buffer,
3099 ModestMsgEditWindow *editor)
3101 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3102 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3106 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3108 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3109 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3113 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3116 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3117 GtkTextBuffer *buffer;
3119 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3120 gtk_text_buffer_set_modified (buffer, modified);
3121 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3122 gtk_text_buffer_set_modified (buffer, modified);
3123 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3124 gtk_text_buffer_set_modified (buffer, modified);
3125 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3129 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3131 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3132 const char *account_name;
3133 GtkTextBuffer *buffer;
3135 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3136 if (gtk_text_buffer_get_modified (buffer))
3138 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3139 if (gtk_text_buffer_get_modified (buffer))
3141 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3142 if (gtk_text_buffer_get_modified (buffer))
3144 if (gtk_text_buffer_get_modified (priv->text_buffer))
3146 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3147 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3158 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3160 ModestMsgEditWindowPrivate *priv = NULL;
3162 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3163 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3165 /* check if there's no recipient added */
3166 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3167 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3168 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3169 /* no recipient contents, then select contacts */
3170 modest_msg_edit_window_open_addressbook (window, NULL);
3174 g_object_ref (window);
3175 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3176 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3177 g_object_unref (window);
3180 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3181 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3182 g_object_unref (window);
3185 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3186 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3187 g_object_unref (window);
3191 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3192 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3193 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3194 g_object_unref (window);
3201 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3202 ModestMsgEditWindow *window)
3204 modest_msg_edit_window_offer_attach_file (window);
3208 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3210 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3212 return priv->clipboard_text;
3216 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3218 ModestMsgEditWindow *window)
3220 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3221 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3223 if (!GTK_WIDGET_VISIBLE (window))
3226 g_object_ref (window);
3227 text = gtk_clipboard_wait_for_text (selection_clipboard);
3229 if (priv->clipboard_text != NULL) {
3230 g_free (priv->clipboard_text);
3232 priv->clipboard_text = text;
3234 if (GTK_WIDGET_VISIBLE (window)) {
3235 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3237 g_object_unref (window);
3240 static gboolean clipboard_owner_change_idle (gpointer userdata)
3242 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3243 ModestMsgEditWindowPrivate *priv;
3245 gdk_threads_enter ();
3246 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3247 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3249 priv->clipboard_owner_idle = 0;
3250 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3251 gdk_threads_leave ();
3257 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3259 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3260 if (priv->clipboard_owner_idle == 0) {
3261 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3266 subject_field_move_cursor (GtkEntry *entry,
3267 GtkMovementStep step,
3272 if (!GTK_WIDGET_VISIBLE (window))
3275 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3279 update_window_title (ModestMsgEditWindow *window)
3281 ModestMsgEditWindowPrivate *priv = NULL;
3282 const gchar *subject;
3284 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3285 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3286 if (subject == NULL || subject[0] == '\0')
3287 subject = _("mail_va_new_email");
3289 gtk_window_set_title (GTK_WINDOW (window), subject);
3294 subject_field_changed (GtkEditable *editable,
3295 ModestMsgEditWindow *window)
3297 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3298 update_window_title (window);
3299 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3300 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3301 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3305 subject_field_insert_text (GtkEditable *editable,
3307 gint new_text_length,
3309 ModestMsgEditWindow *window)
3311 GString *result = g_string_new ("");
3313 gint result_len = 0;
3314 const gchar *entry_text = NULL;
3317 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3318 old_length = g_utf8_strlen (entry_text, -1);
3320 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3321 gunichar c = g_utf8_get_char_validated (current, 8);
3322 /* Invalid unichar, stop */
3328 result = g_string_append_unichar (result, c);
3332 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3333 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3336 /* Prevent endless recursion */
3337 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3338 g_signal_emit_by_name (editable, "insert-text",
3339 (gpointer) result->str, (gpointer) result->len,
3340 (gpointer) position, (gpointer) window);
3341 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3345 if (result_len + old_length > 1000) {
3346 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3347 _CS("ckdg_ib_maximum_characters_reached"));
3349 g_string_free (result, TRUE);
3353 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3356 ModestMsgEditWindowPrivate *priv = NULL;
3358 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3359 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3361 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3364 gtk_widget_show_all (priv->find_toolbar);
3365 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3367 gtk_widget_hide_all (priv->find_toolbar);
3368 gtk_widget_grab_focus (priv->msg_body);
3373 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3375 GtkTextIter *match_start,
3376 GtkTextIter *match_end)
3378 GtkTextIter end_iter;
3379 gchar *str_casefold;
3382 gchar *range_casefold;
3385 gboolean result = FALSE;
3392 gtk_text_iter_forward_to_end (&end_iter);
3394 str_casefold = g_utf8_casefold (str, -1);
3395 str_chars_n = strlen (str);
3397 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3398 range_casefold = g_utf8_casefold (range_text, -1);
3399 range_chars_n = strlen (range_casefold);
3401 if (range_chars_n < str_chars_n) {
3402 g_free (str_casefold);
3403 g_free (range_text);
3404 g_free (range_casefold);
3408 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3409 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3410 if (!g_utf8_collate (range_subtext, str_casefold)) {
3411 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3413 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3414 match_start, match_end, NULL);
3415 g_free (found_text);
3417 g_free (range_subtext);
3421 g_free (str_casefold);
3422 g_free (range_text);
3423 g_free (range_casefold);
3430 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3431 ModestMsgEditWindow *window)
3433 gchar *current_search = NULL;
3434 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3436 GtkTextIter selection_start, selection_end;
3437 GtkTextIter match_start, match_end;
3438 gboolean continue_search = FALSE;
3440 if (message_is_empty (window)) {
3441 g_free (priv->last_search);
3442 priv->last_search = NULL;
3443 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3447 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3448 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3449 g_free (current_search);
3450 g_free (priv->last_search);
3451 priv->last_search = NULL;
3452 /* Information banner about empty search */
3453 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3457 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3458 continue_search = TRUE;
3460 g_free (priv->last_search);
3461 priv->last_search = g_strdup (current_search);
3464 if (continue_search) {
3465 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3466 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3467 &match_start, &match_end);
3469 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3471 GtkTextIter buffer_start;
3472 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3473 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3474 &match_start, &match_end);
3476 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3479 /* Mark as selected the string found in search */
3481 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3482 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3483 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3485 g_free (priv->last_search);
3486 priv->last_search = NULL;
3488 g_free (current_search);
3492 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3494 ModestMsgEditWindowPrivate *priv;
3496 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3501 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3504 ModestMsgEditWindowPrivate *priv;
3506 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3511 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3512 ModestMsgEditWindow *window)
3514 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3518 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3521 ModestMsgEditWindowPrivate *priv;
3522 TnyHeader *header = NULL;
3524 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3525 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3527 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3528 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3530 if (priv->draft_msg != NULL) {
3531 g_object_unref (priv->draft_msg);
3534 if (draft != NULL) {
3535 g_object_ref (draft);
3536 header = tny_msg_get_header (draft);
3537 if (priv->msg_uid) {
3538 g_free (priv->msg_uid);
3539 priv->msg_uid = NULL;
3541 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3542 if (GTK_WIDGET_REALIZED (window)) {
3543 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3544 gtk_widget_destroy (GTK_WIDGET (window));
3550 priv->draft_msg = draft;
3554 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3555 GtkTextIter *start, GtkTextIter *end,
3558 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3559 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3562 if (tag == NULL) return;
3563 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3564 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3565 replace_with_images (window, priv->images);
3570 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3573 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3575 g_return_if_fail (TNY_IS_MIME_PART (part));
3576 tny_list_prepend (priv->attachments, (GObject *) part);
3577 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3578 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3579 gtk_widget_show_all (priv->attachments_caption);
3580 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3584 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3586 ModestMsgEditWindowPrivate *priv;
3588 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3589 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3591 return priv->msg_uid;
3595 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3596 ModestMsgEditWindowWidgetType widget_type)
3598 ModestMsgEditWindowPrivate *priv;
3600 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3601 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3603 switch (widget_type) {
3604 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3605 return priv->msg_body;
3607 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3608 return priv->to_field;
3610 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3611 return priv->cc_field;
3613 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3614 return priv->bcc_field;
3616 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3617 return priv->subject_field;
3619 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3620 return priv->attachments_view;
3628 remove_tags (WPTextBuffer *buffer)
3630 GtkTextIter start, end;
3632 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3633 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3635 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3639 on_account_removed (TnyAccountStore *account_store,
3640 TnyAccount *account,
3643 /* Do nothing if it's a store account, because we use the
3644 transport to send the messages */
3645 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3646 const gchar *parent_acc = NULL;
3647 const gchar *our_acc = NULL;
3649 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3650 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3651 /* Close this window if I'm showing a message of the removed account */
3652 if (strcmp (parent_acc, our_acc) == 0)
3653 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3658 from_field_changed (HildonPickerButton *button,
3659 ModestMsgEditWindow *self)
3661 ModestMsgEditWindowPrivate *priv;
3662 gboolean has_old_signature, has_new_signature;
3664 GtkTextIter match_start, match_end;
3665 ModestAccountMgr *mgr;
3667 gchar *full_signature;
3669 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3671 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3672 mgr = modest_runtime_get_account_mgr ();
3673 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3674 if (has_old_signature) {
3675 full_signature = g_strconcat ("\n--\n", signature, NULL);
3676 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3677 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3679 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3680 &match_start, &match_end, NULL)) {
3683 g_free (full_signature);
3687 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3688 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3689 if (has_new_signature) {
3690 full_signature = g_strconcat ("\n--\n", signature, NULL);
3691 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3692 g_free (full_signature);
3697 typedef struct _MessageSettingsHelper {
3698 ModestMsgEditWindow *window;
3699 GSList *priority_group;
3700 GSList *format_group;
3701 GtkToggleButton *current_priority;
3702 GtkToggleButton *current_format;
3703 } MessageSettingsHelper;
3706 on_priority_toggle (GtkToggleButton *button,
3707 MessageSettingsHelper *helper)
3710 ModestMsgEditWindowPrivate *priv;
3712 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3713 if (gtk_toggle_button_get_active (button)) {
3715 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3716 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3717 if ((node_button != button) &&
3718 gtk_toggle_button_get_active (node_button)) {
3719 gtk_toggle_button_set_active (node_button, FALSE);
3722 helper->current_priority = button;
3724 gboolean found = FALSE;
3725 /* If no one is active, activate it again */
3726 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3727 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3728 if (gtk_toggle_button_get_active (node_button)) {
3734 gtk_toggle_button_set_active (button, TRUE);
3740 on_format_toggle (GtkToggleButton *button,
3741 MessageSettingsHelper *helper)
3744 ModestMsgEditWindowPrivate *priv;
3746 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3747 if (gtk_toggle_button_get_active (button)) {
3749 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3750 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3751 if ((node_button != button) &&
3752 gtk_toggle_button_get_active (node_button)) {
3753 gtk_toggle_button_set_active (node_button, FALSE);
3756 helper->current_format = button;
3758 gboolean found = FALSE;
3759 /* If no one is active, activate it again */
3760 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3761 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3762 if (gtk_toggle_button_get_active (node_button)) {
3768 gtk_toggle_button_set_active (button, TRUE);
3775 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3780 GtkWidget *priority_hbox;
3781 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3782 GtkWidget *captioned;
3783 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3784 GtkWidget *format_hbox;
3785 GtkWidget *html_toggle, *text_toggle;
3786 ModestMsgEditWindowPrivate *priv;
3787 MessageSettingsHelper helper = {0,};
3789 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3790 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3791 helper.window = window;
3792 helper.priority_group = NULL;
3793 helper.format_group = NULL;
3795 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3796 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3798 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3799 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3800 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3801 vbox = gtk_vbox_new (FALSE, 0);
3802 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
3803 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
3804 gtk_container_add (GTK_CONTAINER (align), vbox);
3805 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
3806 gtk_widget_show (align);
3807 gtk_widget_show (vbox);
3809 /* Priority toggles */
3810 priority_hbox = gtk_hbox_new (TRUE, 0);
3811 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3812 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3813 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3814 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3815 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3816 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3817 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3818 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3819 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3820 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3821 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3822 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3823 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3824 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3825 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3826 gtk_widget_show_all (priority_hbox);
3827 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3828 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3829 gtk_widget_show (captioned);
3830 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3832 /* format toggles */
3833 format_hbox = gtk_hbox_new (TRUE, 0);
3834 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3835 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3836 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3837 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3838 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3839 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3840 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3841 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3842 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3843 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3844 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3845 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3846 gtk_widget_show_all (format_hbox);
3847 gtk_widget_show (format_hbox);
3848 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3851 g_object_unref (title_sizegroup);
3852 g_object_unref (value_sizegroup);
3854 /* Set current values */
3855 switch (priv->priority_flags) {
3856 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3857 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3858 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3860 case TNY_HEADER_FLAG_LOW_PRIORITY:
3861 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3862 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3865 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3866 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3870 switch (modest_msg_edit_window_get_format (window)) {
3871 case MODEST_MSG_EDIT_FORMAT_TEXT:
3872 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3873 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3875 case MODEST_MSG_EDIT_FORMAT_HTML:
3877 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3878 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3882 /* Signal connects */
3883 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3884 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3885 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3886 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3887 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3889 /* Save settings if the user clicked on done */
3890 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3891 TnyHeaderFlags flags;
3892 ModestMsgEditFormat old_format, new_format;
3894 /* Set priority flags */
3895 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3896 if (priv->priority_flags != flags)
3897 modest_msg_edit_window_set_priority_flags (window, flags);
3899 /* Set edit format */
3900 old_format = modest_msg_edit_window_get_format (window);
3901 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3902 if (old_format != new_format) {
3903 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3904 modest_msg_edit_window_set_file_format (window, file_format);
3908 gtk_widget_destroy (dialog);
3909 g_slist_free (helper.priority_group);
3913 on_message_settings (GtkAction *action,
3914 ModestMsgEditWindow *window)
3916 modest_msg_edit_window_show_msg_settings_dialog (window);
3920 on_cc_button_toggled (HildonCheckButton *button,
3921 ModestMsgEditWindow *window)
3923 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3925 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3926 hildon_check_button_get_active (button));
3930 on_bcc_button_toggled (HildonCheckButton *button,
3931 ModestMsgEditWindow *window)
3933 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3935 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3936 hildon_check_button_get_active (button));
3940 setup_menu (ModestMsgEditWindow *self)
3942 ModestMsgEditWindowPrivate *priv = NULL;
3944 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3946 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3948 /* Settings menu buttons */
3949 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3950 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3952 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3953 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3954 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3956 priv->cc_button = hildon_check_button_new (0);
3957 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3958 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3960 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3962 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3963 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3964 priv->bcc_button = hildon_check_button_new (0);
3965 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3966 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3968 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3970 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3971 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3973 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3974 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3975 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3976 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3977 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3978 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3979 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3980 APP_MENU_CALLBACK (on_message_settings),
3982 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3983 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),