1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
42 #include <modest-account-mgr.h>
43 #include <modest-account-mgr-helpers.h>
45 #include <widgets/modest-msg-edit-window.h>
46 #include <modest-selector-picker.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <modest-wp-text-view.h>
65 #include <wptextbuffer.h>
66 #include <hildon/hildon-pannable-area.h>
67 #include <hildon/hildon-touch-selector.h>
68 #include <hildon/hildon-picker-dialog.h>
69 #include "modest-msg-edit-window-ui-dimming.h"
71 #include "modest-hildon-includes.h"
72 #ifdef MODEST_HAVE_HILDON0_WIDGETS
73 #include <hildon-widgets/hildon-color-chooser.h>
75 #include "widgets/modest-msg-edit-window-ui.h"
76 #ifdef MODEST_HAVE_HILDON0_WIDGETS
77 #include <libgnomevfs/gnome-vfs-mime-utils.h>
79 #include <libgnomevfs/gnome-vfs-mime.h>
81 #include <modest-utils.h>
82 #include "modest-maemo-utils.h"
83 #include <modest-ui-constants.h>
86 #define DEFAULT_FONT_SIZE 3
87 #define DEFAULT_FONT 2
88 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
89 #define DEFAULT_MAIN_VBOX_SPACING 6
90 #define SUBJECT_MAX_LENGTH 1000
91 #define IMAGE_MAX_WIDTH 560
92 #define DEFAULT_FONT_SCALE 1.5
93 #define ATTACHMENT_BUTTON_WIDTH 118
95 static gboolean is_wp_text_buffer_started = FALSE;
97 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
98 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
99 static void modest_msg_edit_window_finalize (GObject *obj);
101 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
102 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
103 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
105 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
106 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
107 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
108 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
109 GtkTextIter *start, GtkTextIter *end,
111 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
112 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
113 static void subject_field_insert_text (GtkEditable *editable,
115 gint new_text_length,
117 ModestMsgEditWindow *window);
118 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
120 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
122 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
123 ModestRecptEditor *editor);
124 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
125 ModestMsgEditWindow *window);
127 /* ModestWindow methods implementation */
128 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
129 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
130 gboolean show_toolbar);
131 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
133 ModestMsgEditWindow *window);
134 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
135 static void subject_field_move_cursor (GtkEntry *entry,
136 GtkMovementStep step,
140 static void update_window_title (ModestMsgEditWindow *window);
143 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
144 ModestMsgEditWindow *window);
145 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
146 ModestMsgEditWindow *window);
147 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
149 GtkTextIter *match_start,
150 GtkTextIter *match_end);
152 static void remove_tags (WPTextBuffer *buffer);
154 static void on_account_removed (TnyAccountStore *account_store,
158 static void init_window (ModestMsgEditWindow *obj);
160 gboolean scroll_drag_timeout (gpointer userdata);
161 static void correct_scroll (ModestMsgEditWindow *w);
162 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
163 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
164 ModestMsgEditWindow *userdata);
165 static void text_buffer_mark_set (GtkTextBuffer *buffer,
168 ModestMsgEditWindow *userdata);
169 static void on_message_settings (GtkAction *action,
170 ModestMsgEditWindow *window);
171 static void setup_menu (ModestMsgEditWindow *self);
173 static void from_field_changed (HildonPickerButton *button,
174 ModestMsgEditWindow *self);
175 static void font_size_clicked (GtkToolButton *button,
176 ModestMsgEditWindow *window);
177 static void font_face_clicked (GtkToolButton *button,
178 ModestMsgEditWindow *window);
179 static void DEBUG_BUFFER (WPTextBuffer *buffer)
183 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
185 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
186 while (!gtk_text_iter_is_end (&iter)) {
187 GString *output = g_string_new ("");
188 GSList *toggled_tags;
191 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
192 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
193 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
194 GtkTextTag *tag = (GtkTextTag *) node->data;
196 g_object_get (G_OBJECT (tag), "name", &name, NULL);
197 output = g_string_append (output, name);
198 g_string_append (output, " ");
200 output = g_string_append (output, "] OPENED [ ");
201 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
202 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
203 GtkTextTag *tag = (GtkTextTag *) node->data;
205 g_object_get (G_OBJECT (tag), "name", &name, NULL);
206 output = g_string_append (output, name);
207 g_string_append (output, " ");
209 output = g_string_append (output, "]\n");
210 g_message ("%s", output->str);
211 g_string_free (output, TRUE);
212 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
214 g_message ("END BUFFER");
218 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
219 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
223 /* static gboolean */
224 /* on_key_pressed (GtkWidget *self, */
225 /* GdkEventKey *event, */
226 /* gpointer user_data); */
228 /* list my signals */
235 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
236 struct _ModestMsgEditWindowPrivate {
238 GtkWidget *header_box;
240 ModestPairList *from_field_protos;
241 GtkWidget *from_field;
242 gchar *last_from_account;
243 gchar *original_account_name;
247 GtkWidget *bcc_field;
248 GtkWidget *subject_field;
249 GtkWidget *attachments_view;
250 GtkWidget *priority_icon;
251 GtkWidget *subject_box;
252 GtkWidget *add_attachment_button;
254 GtkWidget *cc_caption;
255 GtkWidget *bcc_caption;
256 gboolean update_caption_visibility;
257 GtkWidget *attachments_caption;
259 GtkTextBuffer *text_buffer;
261 GtkWidget *font_size_toolitem;
262 GtkWidget *font_face_toolitem;
263 GtkWidget *font_color_button;
264 GtkWidget *font_color_toolitem;
265 GSList *font_items_group;
266 GtkTreeModel *faces_model;
267 gint current_face_index;
268 GtkWidget *font_tool_button_label;
269 GtkTreeModel *sizes_model;
270 gint current_size_index;
271 GtkWidget *size_tool_button_label;
273 GtkWidget *find_toolbar;
276 GtkWidget *font_dialog;
279 guint correct_scroll_idle;
280 guint scroll_drag_timeout_id;
284 TnyList *attachments;
289 TnyHeaderFlags priority_flags;
291 gboolean can_undo, can_redo;
292 gulong clipboard_change_handler_id;
293 gulong default_clipboard_change_handler_id;
294 gulong account_removed_handler_id;
295 guint clipboard_owner_idle;
296 gchar *clipboard_text;
305 GtkWidget *cc_button;
306 GtkWidget *bcc_button;
309 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
310 MODEST_TYPE_MSG_EDIT_WINDOW, \
311 ModestMsgEditWindowPrivate))
313 static GtkWindowClass *parent_class = NULL;
315 /* uncomment the following if you have defined any signals */
316 /* static guint signals[LAST_SIGNAL] = {0}; */
319 modest_msg_edit_window_get_type (void)
321 static GType my_type = 0;
323 static const GTypeInfo my_info = {
324 sizeof(ModestMsgEditWindowClass),
325 NULL, /* base init */
326 NULL, /* base finalize */
327 (GClassInitFunc) modest_msg_edit_window_class_init,
328 NULL, /* class finalize */
329 NULL, /* class data */
330 sizeof(ModestMsgEditWindow),
332 (GInstanceInitFunc) modest_msg_edit_window_init,
335 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
336 "ModestMsgEditWindow",
344 save_state (ModestWindow *self)
346 modest_widget_memory_save (modest_runtime_get_conf(),
347 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
352 restore_settings (ModestMsgEditWindow *self)
354 ModestConf *conf = NULL;
356 conf = modest_runtime_get_conf ();
358 /* Dim at start clipboard actions */
359 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
364 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
366 GObjectClass *gobject_class;
367 ModestWindowClass *modest_window_class;
368 gobject_class = (GObjectClass*) klass;
369 modest_window_class = (ModestWindowClass*) klass;
371 parent_class = g_type_class_peek_parent (klass);
372 gobject_class->finalize = modest_msg_edit_window_finalize;
374 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
375 modest_window_class->save_state_func = save_state;
376 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
378 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
382 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
384 ModestMsgEditWindowPrivate *priv;
385 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
387 priv->msg_body = NULL;
388 priv->from_field = NULL;
389 priv->to_field = NULL;
390 priv->cc_field = NULL;
391 priv->bcc_field = NULL;
392 priv->subject_field = NULL;
393 priv->attachments = TNY_LIST (tny_simple_list_new ());
394 priv->images = TNY_LIST (tny_simple_list_new ());
395 priv->images_size = 0;
396 priv->images_count = 0;
399 priv->cc_caption = NULL;
400 priv->bcc_caption = NULL;
401 priv->update_caption_visibility = FALSE;
403 priv->priority_flags = 0;
405 priv->find_toolbar = NULL;
406 priv->last_search = NULL;
408 priv->draft_msg = NULL;
409 priv->outbox_msg = NULL;
410 priv->msg_uid = NULL;
412 priv->can_undo = FALSE;
413 priv->can_redo = FALSE;
414 priv->clipboard_change_handler_id = 0;
415 priv->default_clipboard_change_handler_id = 0;
416 priv->account_removed_handler_id = 0;
417 priv->clipboard_owner_idle = 0;
418 priv->clipboard_text = NULL;
421 priv->scroll_drag_timeout_id = 0;
422 priv->correct_scroll_idle = 0;
423 priv->last_upper = 0.0;
425 priv->font_dialog = NULL;
426 priv->app_menu = NULL;
428 if (!is_wp_text_buffer_started) {
429 is_wp_text_buffer_started = TRUE;
430 wp_text_buffer_library_init ();
435 hildon_program_add_window (hildon_program_get_instance(),
441 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
443 static ModestPairList*
444 get_transports (void)
446 GSList *transports = NULL;
448 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
449 GSList *accounts = modest_account_mgr_account_names (account_mgr,
450 TRUE /* only enabled accounts. */);
452 GSList *cursor = accounts;
454 gchar *account_name = cursor->data;
455 gchar *from_string = NULL;
457 from_string = modest_account_mgr_get_from_string (account_mgr,
461 if (from_string && account_name) {
462 gchar *name = account_name;
463 ModestPair *pair = modest_pair_new ((gpointer) name,
464 (gpointer) from_string , TRUE);
465 transports = g_slist_prepend (transports, pair);
468 cursor = cursor->next;
470 g_slist_free (accounts); /* only free the accounts, not the elements,
471 * because they are used in the pairlist */
475 static void window_focus (GtkWindow *window,
479 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
483 scroll_drag_timeout (gpointer userdata)
485 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
486 ModestMsgEditWindowPrivate *priv;
488 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
490 correct_scroll_without_drag_check (win, TRUE);
492 priv->scroll_drag_timeout_id = 0;
498 correct_scroll_without_drag_check_idle (gpointer userdata)
500 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
501 ModestMsgEditWindowPrivate *priv;
503 GdkRectangle rectangle;
504 gint offset_min, offset_max;
508 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
510 insert = gtk_text_buffer_get_insert (priv->text_buffer);
511 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
513 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
514 offset_min = priv->msg_body->allocation.y + rectangle.y;
515 offset_max = offset_min + rectangle.height;
517 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
518 offset_min = MAX (offset_min - 48, 0);
519 offset_max = MIN (offset_max + 48, vadj->upper);
521 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
523 priv->correct_scroll_idle = 0;
528 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
530 ModestMsgEditWindowPrivate *priv;
532 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
534 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
537 if (priv->correct_scroll_idle > 0) {
541 priv->correct_scroll_idle = g_idle_add ((GSourceFunc) correct_scroll_without_drag_check_idle,
546 correct_scroll (ModestMsgEditWindow *w)
548 ModestMsgEditWindowPrivate *priv;
550 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
551 if (gtk_grab_get_current () == priv->msg_body) {
552 if (priv->scroll_drag_timeout_id == 0) {
553 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
559 correct_scroll_without_drag_check (w, TRUE);
563 text_buffer_end_user_action (GtkTextBuffer *buffer,
564 ModestMsgEditWindow *userdata)
567 correct_scroll (userdata);
571 text_buffer_mark_set (GtkTextBuffer *buffer,
574 ModestMsgEditWindow *userdata)
576 gtk_text_buffer_begin_user_action (buffer);
577 gtk_text_buffer_end_user_action (buffer);
581 cut_clipboard_check (GtkTextView *text_view,
584 GtkTextBuffer *buffer;
586 buffer = gtk_text_view_get_buffer (text_view);
587 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
588 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
593 copy_clipboard_check (GtkTextView *text_view,
596 GtkTextBuffer *buffer;
598 buffer = gtk_text_view_get_buffer (text_view);
599 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
600 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
605 attachment_deleted (ModestAttachmentsView *attachments_view,
608 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
613 connect_signals (ModestMsgEditWindow *obj)
615 ModestMsgEditWindowPrivate *priv;
617 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
619 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
620 G_CALLBACK (text_buffer_refresh_attributes), obj);
621 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
622 G_CALLBACK (text_buffer_can_undo), obj);
623 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
624 G_CALLBACK (text_buffer_can_redo), obj);
625 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
626 G_CALLBACK (body_changed), obj);
627 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
628 G_CALLBACK (body_changed), obj);
629 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
630 G_CALLBACK (text_buffer_end_user_action), obj);
631 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
632 G_CALLBACK (text_buffer_mark_set), obj);
633 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
634 G_CALLBACK (text_buffer_apply_tag), obj);
635 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
636 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
637 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
638 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
639 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
640 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
642 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
643 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
644 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
645 G_CALLBACK (from_field_changed), obj);
647 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
648 G_CALLBACK (msg_body_focus), obj);
649 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
650 G_CALLBACK (msg_body_focus), obj);
651 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
652 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
653 "changed", G_CALLBACK (recpt_field_changed), obj);
654 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
655 "changed", G_CALLBACK (recpt_field_changed), obj);
656 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
657 "changed", G_CALLBACK (recpt_field_changed), obj);
658 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
659 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
660 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
662 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
663 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
665 priv->clipboard_change_handler_id =
666 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
667 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
668 priv->default_clipboard_change_handler_id =
669 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
670 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
672 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
673 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
674 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
678 init_wp_text_view_style ()
680 static gboolean initialized = FALSE;
683 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
689 init_window (ModestMsgEditWindow *obj)
691 GtkWidget *to_caption, *subject_caption;
692 GtkWidget *main_vbox;
693 GtkWidget *add_attachment_align;
694 ModestMsgEditWindowPrivate *priv;
695 GtkActionGroup *action_group;
696 ModestWindowPrivate *parent_priv;
697 GdkPixbuf *window_icon = NULL;
698 GError *error = NULL;
700 GtkSizeGroup *title_size_group;
701 GtkSizeGroup *value_size_group;
702 GtkWidget *attachment_icon;
703 GtkWidget *window_box;
704 GtkWidget *window_align;
705 #if (GTK_MINOR_VERSION >= 10)
706 GdkAtom deserialize_type;
709 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
710 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
712 parent_priv->ui_manager = gtk_ui_manager_new();
713 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
714 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
716 /* Add common actions */
717 gtk_action_group_add_actions (action_group,
718 modest_msg_edit_action_entries,
719 G_N_ELEMENTS (modest_msg_edit_action_entries),
721 gtk_action_group_add_actions (action_group,
722 hildon2_msg_edit_action_entries,
723 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
725 gtk_action_group_add_toggle_actions (action_group,
726 modest_msg_edit_toggle_action_entries,
727 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
729 gtk_action_group_add_radio_actions (action_group,
730 modest_msg_edit_alignment_radio_action_entries,
731 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
733 G_CALLBACK (modest_ui_actions_on_change_justify),
735 gtk_action_group_add_radio_actions (action_group,
736 modest_msg_edit_priority_action_entries,
737 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
739 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
741 gtk_action_group_add_radio_actions (action_group,
742 modest_msg_edit_file_format_action_entries,
743 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
744 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
745 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
747 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
748 g_object_unref (action_group);
750 /* Load the UI definition */
751 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
754 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
755 g_clear_error (&error);
758 /* Add accelerators */
759 gtk_window_add_accel_group (GTK_WINDOW (obj),
760 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
762 parent_priv->menubar = NULL;
764 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
765 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
767 /* Note: This ModestPairList* must exist for as long as the picker
768 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
769 * so it can't know how to manage its memory. */
770 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
771 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
773 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
774 _("mail_va_from"), priv->from_field);
776 priv->to_field = modest_recpt_editor_new ();
777 priv->cc_field = modest_recpt_editor_new ();
778 priv->bcc_field = modest_recpt_editor_new ();
779 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
780 priv->priority_icon = gtk_image_new ();
781 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
782 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
783 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
784 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
785 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
786 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
787 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
788 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
789 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
790 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
791 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
792 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
793 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
794 add_attachment_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
795 gtk_alignment_set_padding (GTK_ALIGNMENT (add_attachment_align), 0, 0, MODEST_MARGIN_DEFAULT, 0);
796 gtk_container_add (GTK_CONTAINER (add_attachment_align), priv->add_attachment_button);
797 gtk_box_pack_start (GTK_BOX (priv->subject_box), add_attachment_align, FALSE, FALSE, 0);
798 priv->attachments_view = modest_attachments_view_new (NULL);
799 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
800 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
802 priv->header_box = gtk_vbox_new (FALSE, 0);
804 to_caption = modest_maemo_utils_create_captioned_with_size_type
805 (title_size_group, value_size_group,
806 _("mail_va_to"), FALSE, priv->to_field,
807 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
808 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
809 (title_size_group, value_size_group,
810 _("mail_va_cc"), FALSE, priv->cc_field,
811 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
812 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
813 (title_size_group, value_size_group,
814 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
815 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
816 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
817 _("mail_va_subject"), FALSE, priv->subject_box);
818 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
819 _("mail_va_attachment"),
821 priv->attachments_view,
822 HILDON_SIZE_AUTO_WIDTH |
823 HILDON_SIZE_AUTO_HEIGHT);
824 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
825 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
826 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
827 g_object_unref (title_size_group);
828 g_object_unref (value_size_group);
830 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
831 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
832 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
833 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
834 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
835 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
836 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
838 init_wp_text_view_style ();
840 priv->msg_body = modest_wp_text_view_new ();
843 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
844 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
845 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
846 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
847 #if (GTK_MINOR_VERSION >= 10)
848 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
849 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
851 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
852 deserialize_type, TRUE);
854 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
856 priv->find_toolbar = hildon_find_toolbar_new (NULL);
857 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
859 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
861 priv->pannable = hildon_pannable_area_new ();
863 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
864 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
865 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
867 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
868 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
869 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
871 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
872 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox),
873 hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable)));
874 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
876 window_box = gtk_vbox_new (FALSE, 0);
877 gtk_container_add (GTK_CONTAINER(obj), window_box);
879 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
881 /* Set window icon */
882 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
884 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
885 g_object_unref (window_icon);
890 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
892 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
894 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
895 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
896 priv->clipboard_change_handler_id))
897 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
898 priv->clipboard_change_handler_id);
899 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
900 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
901 priv->default_clipboard_change_handler_id))
902 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
903 priv->default_clipboard_change_handler_id);
905 if (priv->account_removed_handler_id &&
906 g_signal_handler_is_connected (modest_runtime_get_account_store (),
907 priv->account_removed_handler_id))
908 g_signal_handler_disconnect(modest_runtime_get_account_store (),
909 priv->account_removed_handler_id);
913 modest_msg_edit_window_finalize (GObject *obj)
915 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
917 /* Sanity check: shouldn't be needed, the window mgr should
918 call this function before */
919 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
921 if (priv->font_dialog != NULL) {
922 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
925 if (priv->clipboard_text != NULL) {
926 g_free (priv->clipboard_text);
927 priv->clipboard_text = NULL;
930 if (priv->draft_msg != NULL) {
931 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
932 if (TNY_IS_HEADER (header)) {
933 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
934 modest_window_mgr_unregister_header (mgr, header);
936 g_object_unref (priv->draft_msg);
937 priv->draft_msg = NULL;
939 if (priv->outbox_msg != NULL) {
940 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
941 if (TNY_IS_HEADER (header)) {
942 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
943 modest_window_mgr_unregister_header (mgr, header);
945 g_object_unref (priv->outbox_msg);
946 priv->outbox_msg = NULL;
948 if (priv->correct_scroll_idle > 0) {
949 g_source_remove (priv->correct_scroll_idle);
950 priv->correct_scroll_idle = 0;
952 if (priv->scroll_drag_timeout_id > 0) {
953 g_source_remove (priv->scroll_drag_timeout_id);
954 priv->scroll_drag_timeout_id = 0;
956 if (priv->clipboard_owner_idle > 0) {
957 g_source_remove (priv->clipboard_owner_idle);
958 priv->clipboard_owner_idle = 0;
960 if (priv->original_account_name)
961 g_free (priv->original_account_name);
962 g_free (priv->msg_uid);
963 g_free (priv->last_search);
964 g_object_unref (priv->faces_model);
965 g_object_unref (priv->sizes_model);
966 g_object_unref (priv->attachments);
967 g_object_unref (priv->images);
969 /* This had to stay alive for as long as the picker that used it: */
970 modest_pair_list_free (priv->from_field_protos);
972 G_OBJECT_CLASS(parent_class)->finalize (obj);
976 pixbuf_from_stream (TnyStream *stream,
977 const gchar *mime_type,
978 guint64 *stream_size,
979 ModestMsgEditWindow *self)
981 GdkPixbufLoader *loader;
984 GError *error = NULL;
988 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
990 if (loader == NULL) {
996 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
998 tny_stream_reset (TNY_STREAM (stream));
999 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1000 unsigned char read_buffer[128];
1002 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1004 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1007 /* Allow some UI responsiveness */
1008 while (gtk_events_pending ())
1009 gtk_main_iteration ();
1011 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1013 gdk_pixbuf_loader_close (loader, &error);
1016 g_error_free (error);
1017 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1019 g_object_ref (pixbuf);
1020 g_object_unref (loader);
1025 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1026 GdkPixbuf *new_pixbuf;
1028 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1029 gdk_pixbuf_get_width (pixbuf);
1030 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1031 g_object_unref (pixbuf);
1032 pixbuf = new_pixbuf;
1036 *stream_size = size;
1042 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1044 ModestMsgEditWindowPrivate *priv;
1047 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1049 g_object_ref (self);
1050 for (iter = tny_list_create_iterator (attachments);
1051 !tny_iterator_is_done (iter);
1052 tny_iterator_next (iter)) {
1053 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1054 const gchar *cid = tny_mime_part_get_content_id (part);
1055 const gchar *mime_type = tny_mime_part_get_content_type (part);
1056 if ((cid != NULL)&&(mime_type != NULL)) {
1057 guint64 stream_size;
1058 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1059 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1062 g_object_unref (stream);
1064 if (pixbuf != NULL) {
1065 priv->images_count ++;
1066 priv->images_size += stream_size;
1067 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1068 g_object_unref (pixbuf);
1071 g_object_unref (part);
1073 g_object_unref (iter);
1074 g_object_unref (self);
1078 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1080 TnyMimePart *parent = NULL;
1081 const gchar *content_type = NULL;
1082 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1084 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1086 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1087 parent = g_object_ref (msg);
1088 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1089 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1092 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1093 iter = tny_list_create_iterator (parts);
1094 while (!tny_iterator_is_done (iter)) {
1096 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1097 content_type = tny_mime_part_get_content_type (part);
1098 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1102 g_object_unref (part);
1104 tny_iterator_next (iter);
1106 g_object_unref (iter);
1107 g_object_unref (parts);
1110 if (parent != NULL) {
1111 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1114 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1115 iter = tny_list_create_iterator (parts);
1116 while (!tny_iterator_is_done (iter)) {
1118 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1119 content_type = tny_mime_part_get_content_type (part);
1120 if (content_type && g_str_has_prefix (content_type, "image/")) {
1121 tny_list_prepend (priv->images, (GObject *) part);
1123 g_object_unref (part);
1124 tny_iterator_next (iter);
1126 g_object_unref (iter);
1127 g_object_unref (parts);
1128 g_object_unref (parent);
1133 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1136 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1138 for (iter = tny_list_create_iterator (attachments) ;
1139 !tny_iterator_is_done (iter);
1140 tny_iterator_next (iter)) {
1141 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1142 const gchar *cid = tny_mime_part_get_content_id (part);
1144 char *invalid = NULL;
1145 gint int_cid = strtol (cid, &invalid, 10);
1146 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1147 priv->next_cid = int_cid + 1;
1150 g_object_unref (part);
1152 g_object_unref (iter);
1156 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1159 gchar *to, *cc, *bcc, *subject;
1161 ModestMsgEditWindowPrivate *priv;
1162 ModestWindowPrivate *parent_priv;
1164 TnyHeaderFlags priority_flags;
1165 TnyFolder *msg_folder;
1166 gboolean is_html = FALSE;
1167 gboolean field_view_set;
1169 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1170 g_return_if_fail (TNY_IS_MSG (msg));
1172 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1173 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1175 header = tny_msg_get_header (msg);
1176 to = tny_header_dup_to (header);
1177 cc = tny_header_dup_cc (header);
1178 bcc = tny_header_dup_bcc (header);
1179 subject = tny_header_dup_subject (header);
1180 priority_flags = tny_header_get_priority (header);
1183 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1185 field_view_set = TRUE;
1187 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1188 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1189 gtk_widget_show (priv->cc_caption);
1190 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1191 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1192 gtk_widget_hide (priv->cc_caption);
1193 field_view_set = FALSE;
1195 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1197 field_view_set = TRUE;
1199 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1200 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1201 gtk_widget_show (priv->bcc_caption);
1202 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1203 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1204 gtk_widget_hide (priv->bcc_caption);
1205 field_view_set = FALSE;
1207 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1211 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1212 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1215 update_window_title (self);
1217 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1218 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1220 if ((body == NULL)||(body[0] == '\0')) {
1222 body = modest_text_utils_convert_to_html ("");
1225 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1226 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1229 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1232 /* Add attachments to the view */
1233 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1234 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1235 if (tny_list_get_length (priv->attachments) == 0) {
1236 gtk_widget_hide (priv->attachments_caption);
1238 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1239 gtk_widget_show_all (priv->attachments_caption);
1241 get_related_images (self, msg);
1242 update_next_cid (self, priv->attachments);
1243 update_next_cid (self, priv->images);
1244 replace_with_images (self, priv->images);
1246 if (preserve_is_rich && !is_html) {
1247 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1248 /* Get the default format required from configuration */
1249 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1250 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1253 /* Set the default focus depending on having already a To: field or not */
1254 if ((!to)||(*to == '\0')) {
1255 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1257 gtk_widget_grab_focus (priv->msg_body);
1260 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1262 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1263 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1265 modest_msg_edit_window_set_modified (self, FALSE);
1267 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1268 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1269 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1270 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1272 if (priv->msg_uid) {
1273 g_free (priv->msg_uid);
1274 priv->msg_uid = NULL;
1277 /* we should set a reference to the incoming message if it is a draft */
1278 msg_folder = tny_msg_get_folder (msg);
1280 if (modest_tny_folder_is_local_folder (msg_folder)) {
1281 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1282 if (type == TNY_FOLDER_TYPE_INVALID)
1283 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1285 if (type == TNY_FOLDER_TYPE_DRAFTS)
1286 priv->draft_msg = g_object_ref(msg);
1287 if (type == TNY_FOLDER_TYPE_OUTBOX)
1288 priv->outbox_msg = g_object_ref(msg);
1289 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1291 g_object_unref (msg_folder);
1302 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1304 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1305 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1306 GtkWidget *placeholder;
1307 GtkWidget *tool_item;
1312 GtkWidget *sizes_menu;
1313 GtkWidget *fonts_menu;
1317 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1318 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1319 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1320 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1322 /* Font color placeholder */
1323 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1324 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1327 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1328 priv->font_color_button = hildon_color_button_new ();
1329 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1330 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1331 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1332 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1333 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1334 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1335 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1336 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1338 G_CALLBACK (modest_msg_edit_window_color_button_change),
1341 /* Font size and face placeholder */
1342 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1343 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1345 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1346 priv->size_tool_button_label = gtk_label_new (NULL);
1347 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1348 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1349 size_text, "</span>", NULL);
1350 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1352 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1353 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1354 sizes_menu = gtk_menu_new ();
1355 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1356 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1359 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1360 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1362 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1366 if (wp_font_size[size_index] == 12)
1367 priv->current_size_index = size_index;
1371 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1372 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1373 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1374 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1375 priv->font_size_toolitem = tool_item;
1378 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1379 priv->font_tool_button_label = gtk_label_new (NULL);
1380 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1381 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1383 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1384 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1385 fonts_menu = gtk_menu_new ();
1386 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1387 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1390 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1392 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1393 0, wp_get_font_name (font_index),
1396 if (font_index == DEFAULT_FONT)
1397 priv->current_face_index = font_index;
1399 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1400 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1401 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1402 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1403 priv->font_face_toolitem = tool_item;
1405 /* Set expand and homogeneous for remaining items */
1406 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1407 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1408 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1409 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1410 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1411 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1412 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1413 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1414 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1416 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1417 will not show the tool items added to the placeholders) */
1418 gtk_widget_show_all (parent_priv->toolbar);
1420 /* Set the no show all *after* showing all items. We do not
1421 want the toolbar to be shown with a show all because it
1422 could go agains the gconf setting regarding showing or not
1423 the toolbar of the editor window */
1424 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1430 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1433 ModestWindowPrivate *parent_priv;
1434 ModestMsgEditWindowPrivate *priv;
1435 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1436 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1437 ModestWindowMgr *mgr = NULL;
1439 g_return_val_if_fail (msg, NULL);
1440 g_return_val_if_fail (account_name, NULL);
1442 mgr = modest_runtime_get_window_mgr ();
1444 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1446 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1447 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1449 /* Menubar. Update the state of some toggles */
1450 priv->from_field_protos = get_transports ();
1451 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1452 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1453 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1454 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1456 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1457 hildon_touch_selector_get_current_text
1458 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1459 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1460 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1463 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1465 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1467 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1469 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1471 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1472 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1473 /* Add common dimming rules */
1474 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1475 modest_msg_edit_window_toolbar_dimming_entries,
1476 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1477 MODEST_WINDOW (obj));
1478 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1479 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1480 MODEST_WINDOW (obj));
1481 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1482 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1483 MODEST_WINDOW (obj));
1484 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1485 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1486 MODEST_WINDOW (obj));
1487 /* Insert dimming rules group for this window */
1488 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1489 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1491 /* Setup app menu */
1492 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1494 /* Checks the dimming rules */
1495 g_object_unref (toolbar_rules_group);
1496 g_object_unref (clipboard_rules_group);
1497 gtk_widget_hide (priv->priority_icon);
1498 gtk_widget_queue_resize (priv->subject_box);
1499 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1501 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1503 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1504 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1505 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1506 priv->update_caption_visibility = TRUE;
1508 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1510 /* Track account-removed signal, this window should be closed
1511 in the case we're creating a mail associated to the account
1513 priv->account_removed_handler_id =
1514 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1516 G_CALLBACK(on_account_removed),
1519 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1521 return (ModestWindow*) obj;
1525 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1527 GString **string_buffer = (GString **) user_data;
1529 *string_buffer = g_string_append (*string_buffer, buffer);
1535 * @result: A new string which should be freed with g_free().
1538 get_formatted_data (ModestMsgEditWindow *edit_window)
1540 ModestMsgEditWindowPrivate *priv;
1541 GString *string_buffer = g_string_new ("");
1543 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1545 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1547 modest_text_utils_hyperlinkify (string_buffer);
1549 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1551 return g_string_free (string_buffer, FALSE);
1556 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1559 const gchar *account_name;
1560 ModestMsgEditWindowPrivate *priv;
1561 TnyIterator *att_iter;
1563 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1565 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1567 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1568 g_return_val_if_fail (account_name, NULL);
1571 /* don't free these (except from) */
1572 data = g_slice_new0 (MsgData);
1573 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1575 data->account_name = g_strdup (account_name);
1576 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1577 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1578 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1579 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1580 if (priv->draft_msg) {
1581 data->draft_msg = g_object_ref (priv->draft_msg);
1582 } else if (priv->outbox_msg) {
1583 data->draft_msg = g_object_ref (priv->outbox_msg);
1585 data->draft_msg = NULL;
1588 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1590 gtk_text_buffer_get_bounds (buf, &b, &e);
1591 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1593 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1594 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1596 data->html_body = NULL;
1598 /* deep-copy the data */
1599 att_iter = tny_list_create_iterator (priv->attachments);
1600 data->attachments = NULL;
1601 while (!tny_iterator_is_done (att_iter)) {
1602 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1603 if (!(TNY_IS_MIME_PART(part))) {
1604 g_warning ("strange data in attachment list");
1605 g_object_unref (part);
1606 tny_iterator_next (att_iter);
1609 data->attachments = g_list_append (data->attachments,
1611 tny_iterator_next (att_iter);
1613 g_object_unref (att_iter);
1615 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1616 att_iter = tny_list_create_iterator (priv->images);
1617 data->images = NULL;
1618 while (!tny_iterator_is_done (att_iter)) {
1619 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1621 if (!(TNY_IS_MIME_PART(part))) {
1622 g_warning ("strange data in attachment list");
1623 g_object_unref (part);
1624 tny_iterator_next (att_iter);
1627 cid = tny_mime_part_get_content_id (part);
1629 gchar *image_tag_id;
1630 GtkTextTag *image_tag;
1632 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1633 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1634 g_free (image_tag_id);
1636 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1638 ((gtk_text_iter_has_tag (&iter, image_tag))||
1639 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1640 data->images = g_list_append (data->images,
1641 g_object_ref (part));
1643 g_object_unref (part);
1644 tny_iterator_next (att_iter);
1646 g_object_unref (att_iter);
1648 data->priority_flags = priv->priority_flags;
1655 unref_gobject (GObject *obj, gpointer data)
1657 if (!G_IS_OBJECT(obj))
1659 g_object_unref (obj);
1663 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1666 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1674 g_free (data->from);
1675 g_free (data->subject);
1676 g_free (data->plain_body);
1677 g_free (data->html_body);
1678 g_free (data->account_name);
1680 if (data->draft_msg != NULL) {
1681 g_object_unref (data->draft_msg);
1682 data->draft_msg = NULL;
1685 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1686 g_list_free (data->attachments);
1687 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1688 g_list_free (data->images);
1690 g_slice_free (MsgData, data);
1694 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1696 guint64 *parts_size)
1698 ModestMsgEditWindowPrivate *priv;
1700 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1702 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1704 /* TODO: add images */
1705 *parts_size += priv->images_size;
1706 *parts_count += priv->images_count;
1711 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1714 ModestMsgEditWindowPrivate *priv = NULL;
1715 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1717 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1719 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1721 return MODEST_MSG_EDIT_FORMAT_HTML;
1723 return MODEST_MSG_EDIT_FORMAT_TEXT;
1727 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1728 ModestMsgEditFormat format)
1730 ModestMsgEditWindowPrivate *priv;
1732 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1733 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1736 case MODEST_MSG_EDIT_FORMAT_HTML:
1737 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1739 case MODEST_MSG_EDIT_FORMAT_TEXT:
1740 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1743 g_return_if_reached ();
1747 ModestMsgEditFormatState *
1748 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1750 ModestMsgEditFormatState *format_state = NULL;
1751 ModestMsgEditWindowPrivate *priv;
1752 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1754 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1755 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1757 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1759 format_state = g_new0 (ModestMsgEditFormatState, 1);
1760 format_state->bold = buffer_format->bold&0x1;
1761 format_state->italics = buffer_format->italic&0x1;
1762 format_state->bullet = buffer_format->bullet&0x1;
1763 format_state->color = buffer_format->color;
1764 format_state->font_size = buffer_format->font_size;
1765 format_state->font_family = wp_get_font_name (buffer_format->font);
1766 format_state->justification = buffer_format->justification;
1767 g_free (buffer_format);
1769 return format_state;
1774 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1775 const ModestMsgEditFormatState *format_state)
1777 ModestMsgEditWindowPrivate *priv;
1778 WPTextBufferFormat *buffer_format;
1779 WPTextBufferFormat *current_format;
1781 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1782 g_return_if_fail (format_state != NULL);
1784 buffer_format = g_new0 (WPTextBufferFormat, 1);
1785 current_format = g_new0 (WPTextBufferFormat, 1);
1787 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1788 gtk_widget_grab_focus (priv->msg_body);
1789 buffer_format->bold = (format_state->bold != FALSE);
1790 buffer_format->italic = (format_state->italics != FALSE);
1791 buffer_format->color = format_state->color;
1792 buffer_format->font_size = format_state->font_size;
1793 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1794 buffer_format->justification = format_state->justification;
1795 buffer_format->bullet = format_state->bullet;
1797 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1799 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1800 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1801 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1802 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1803 buffer_format->cs.font = (buffer_format->font != current_format->font);
1804 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1805 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1807 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1808 if (buffer_format->cs.bold) {
1809 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1810 GINT_TO_POINTER (buffer_format->bold&0x1));
1812 if (buffer_format->cs.italic) {
1813 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1814 GINT_TO_POINTER (buffer_format->italic&0x1));
1816 if (buffer_format->cs.color) {
1817 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1818 GINT_TO_POINTER (&(buffer_format->color)));
1820 if (buffer_format->cs.font_size) {
1821 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1822 GINT_TO_POINTER (buffer_format->font_size));
1824 if (buffer_format->cs.justification) {
1825 switch (buffer_format->justification) {
1826 case GTK_JUSTIFY_LEFT:
1827 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1828 GINT_TO_POINTER(TRUE));
1830 case GTK_JUSTIFY_CENTER:
1831 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1832 GINT_TO_POINTER(TRUE));
1834 case GTK_JUSTIFY_RIGHT:
1835 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1836 GINT_TO_POINTER(TRUE));
1843 if (buffer_format->cs.font) {
1844 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1845 GINT_TO_POINTER (buffer_format->font));
1847 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1848 if (buffer_format->cs.bullet) {
1849 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1850 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1852 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1854 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1856 g_free (buffer_format);
1857 g_free (current_format);
1859 /* Check dimming rules */
1860 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1861 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1865 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1867 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1869 ModestWindowPrivate *parent_priv;
1870 ModestMsgEditWindowPrivate *priv;
1872 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1873 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1875 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1876 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1877 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1878 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1880 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1881 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1882 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1885 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1887 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1888 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1890 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1891 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1893 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1894 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1897 switch (buffer_format->justification)
1899 case GTK_JUSTIFY_LEFT:
1900 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1902 case GTK_JUSTIFY_CENTER:
1903 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1905 case GTK_JUSTIFY_RIGHT:
1906 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1913 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1915 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1916 G_CALLBACK (modest_msg_edit_window_color_button_change),
1918 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1919 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1920 G_CALLBACK (modest_msg_edit_window_color_button_change),
1923 if (priv->current_size_index != buffer_format->font_size) {
1927 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
1928 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
1932 priv->current_size_index = buffer_format->font_size;
1934 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
1935 markup = g_strconcat ("<span font_family='Sans'>",
1936 size_text, "</span>", NULL);
1938 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1942 gtk_tree_path_free (path);
1945 if (priv->current_face_index != buffer_format->font) {
1949 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
1950 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
1954 priv->current_face_index = buffer_format->font;
1955 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
1956 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
1957 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1964 g_free (buffer_format);
1968 #ifdef MODEST_HILDON_VERSION_0
1970 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1973 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1974 ModestMsgEditWindowPrivate *priv;
1975 GtkWidget *dialog = NULL;
1977 GdkColor *new_color = NULL;
1979 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1980 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1982 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1983 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1984 g_free (buffer_format);
1986 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
1987 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1988 if (new_color != NULL) {
1989 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1990 (gpointer) new_color);
1993 gtk_widget_destroy (dialog);
1998 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2001 ModestMsgEditWindowPrivate *priv;
2002 GtkWidget *dialog = NULL;
2004 GdkColor *old_color = NULL;
2005 const GdkColor *new_color = NULL;
2007 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2008 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2010 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2011 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2013 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2014 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2015 if (new_color != NULL)
2016 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2018 gtk_widget_destroy (dialog);
2024 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2027 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2028 ModestMsgEditWindowPrivate *priv;
2029 GtkWidget *dialog = NULL;
2031 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2032 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2034 dialog = hildon_color_chooser_new ();
2035 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2036 g_free (buffer_format);
2038 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2040 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2041 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2044 gtk_widget_destroy (dialog);
2049 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2052 ModestMsgEditWindowPrivate *priv;
2053 GtkWidget *dialog = NULL;
2054 GdkColor *old_color = NULL;
2056 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2057 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2059 dialog = hildon_color_chooser_new ();
2060 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2062 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2064 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2065 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2067 gtk_widget_destroy (dialog);
2070 #endif /*!MODEST_HILDON_VERSION_0*/
2075 create_stream_for_uri (const gchar* uri)
2080 TnyStream *result = NULL;
2082 GnomeVFSHandle *handle = NULL;
2083 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2084 if (test == GNOME_VFS_OK) {
2085 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2086 /* Streams over OBEX (Bluetooth) are not seekable but
2087 * we expect them to be (we might need to read them
2088 * several times). So if this is a Bluetooth URI just
2089 * read the whole file into memory (this is not a fast
2090 * protocol so we can assume that these files are not
2091 * going to be very big) */
2092 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2093 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2094 TnyStream *memstream = tny_camel_mem_stream_new ();
2095 tny_stream_write_to_stream (vfssstream, memstream);
2096 g_object_unref (vfssstream);
2099 result = vfssstream;
2107 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2110 ModestMsgEditWindowPrivate *priv;
2111 GtkWidget *dialog = NULL;
2113 GSList *uris = NULL;
2114 GSList *uri_node = NULL;
2116 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2118 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2119 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2120 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2122 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2124 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2125 GTK_WINDOW (dialog), GTK_WINDOW (window));
2127 response = gtk_dialog_run (GTK_DIALOG (dialog));
2129 case GTK_RESPONSE_OK:
2130 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2135 gtk_widget_destroy (dialog);
2137 g_object_ref (window);
2138 /* The operation could take some time so allow the dialog to be closed */
2139 while (gtk_events_pending ())
2140 gtk_main_iteration ();
2142 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2144 GnomeVFSHandle *handle = NULL;
2145 GnomeVFSResult result;
2146 GtkTextIter position;
2147 GtkTextMark *insert_mark;
2149 uri = (const gchar *) uri_node->data;
2150 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2151 if (result == GNOME_VFS_OK) {
2153 GnomeVFSFileInfo *info;
2154 gchar *filename, *basename, *escaped_filename;
2155 TnyMimePart *mime_part;
2157 const gchar *mime_type = NULL;
2158 GnomeVFSURI *vfs_uri;
2159 guint64 stream_size;
2161 gnome_vfs_close (handle);
2162 vfs_uri = gnome_vfs_uri_new (uri);
2164 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2165 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2166 g_free (escaped_filename);
2167 gnome_vfs_uri_unref (vfs_uri);
2168 info = gnome_vfs_file_info_new ();
2170 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2171 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2173 mime_type = gnome_vfs_file_info_get_mime_type (info);
2175 mime_part = tny_platform_factory_new_mime_part
2176 (modest_runtime_get_platform_factory ());
2178 TnyStream *stream = create_stream_for_uri (uri);
2180 if (stream == NULL) {
2182 modest_platform_information_banner (NULL, NULL,
2183 _FM("sfil_ib_opening_not_allowed"));
2185 g_object_unref (mime_part);
2186 gnome_vfs_file_info_unref (info);
2190 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2192 content_id = g_strdup_printf ("%d", priv->next_cid);
2193 tny_mime_part_set_content_id (mime_part, content_id);
2194 g_free (content_id);
2197 basename = g_path_get_basename (filename);
2198 tny_mime_part_set_filename (mime_part, basename);
2201 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2203 if (pixbuf != NULL) {
2204 priv->images_size += stream_size;
2205 priv->images_count ++;
2206 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2207 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2208 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2209 tny_mime_part_get_content_id (mime_part), pixbuf);
2210 g_object_unref (pixbuf);
2212 tny_list_prepend (priv->images, (GObject *) mime_part);
2213 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2215 modest_platform_information_banner (NULL, NULL,
2216 _("mail_ib_file_operation_failed"));
2220 g_object_unref (mime_part);
2221 gnome_vfs_file_info_unref (info);
2225 g_object_unref (window);
2229 on_attach_file_response (GtkDialog *dialog,
2233 GSList *uris = NULL;
2235 GnomeVFSFileSize total_size, allowed_size;
2236 ModestMsgEditWindow *window;
2237 ModestMsgEditWindowPrivate *priv;
2242 case GTK_RESPONSE_OK:
2243 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2249 window = MODEST_MSG_EDIT_WINDOW (user_data);
2250 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2252 /* allowed size is the maximum size - what's already there */
2253 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2254 &att_num, &att_size);
2255 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2258 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2260 const gchar *uri = (const gchar *) uri_node->data;
2263 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2265 if (total_size > allowed_size) {
2266 g_warning ("%s: total size: %u",
2267 __FUNCTION__, (unsigned int)total_size);
2270 allowed_size -= total_size;
2272 g_slist_foreach (uris, (GFunc) g_free, NULL);
2273 g_slist_free (uris);
2275 gtk_widget_destroy (GTK_WIDGET (dialog));
2279 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2281 GtkWidget *dialog = NULL;
2282 ModestMsgEditWindowPrivate *priv;
2284 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2286 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2288 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2291 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2292 GTK_FILE_CHOOSER_ACTION_OPEN);
2293 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2294 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2295 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2296 GTK_WINDOW (dialog), GTK_WINDOW (window));
2298 /* Connect to response & show */
2299 g_signal_connect (dialog, "response",
2300 G_CALLBACK (on_attach_file_response), window);
2301 gtk_widget_show (dialog);
2306 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2308 GnomeVFSFileSize allowed_size)
2311 GnomeVFSHandle *handle = NULL;
2312 ModestMsgEditWindowPrivate *priv;
2313 GnomeVFSResult result;
2314 GnomeVFSFileSize size = 0;
2315 g_return_val_if_fail (window, 0);
2316 g_return_val_if_fail (uri, 0);
2318 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2320 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2321 if (result == GNOME_VFS_OK) {
2322 TnyMimePart *mime_part;
2324 const gchar *mime_type = NULL;
2326 gchar *escaped_filename;
2329 GnomeVFSFileInfo *info;
2330 GnomeVFSURI *vfs_uri;
2332 gnome_vfs_close (handle);
2333 vfs_uri = gnome_vfs_uri_new (uri);
2336 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2337 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2338 g_free (escaped_filename);
2339 gnome_vfs_uri_unref (vfs_uri);
2341 info = gnome_vfs_file_info_new ();
2343 if (gnome_vfs_get_file_info (uri,
2345 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2347 mime_type = gnome_vfs_file_info_get_mime_type (info);
2348 mime_part = tny_platform_factory_new_mime_part
2349 (modest_runtime_get_platform_factory ());
2351 /* try to get the attachment's size; this may fail for weird
2352 * file systems, like obex, upnp... */
2353 if (allowed_size != 0 &&
2354 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2356 if (size > allowed_size) {
2357 modest_platform_information_banner (NULL, NULL,
2358 _FM("sfil_ib_opening_not_allowed"));
2363 g_warning ("%s: could not get attachment size", __FUNCTION__);
2365 stream = create_stream_for_uri (uri);
2367 if (stream == NULL) {
2369 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2371 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;
2539 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2541 memset (&format, 0, sizeof (format));
2542 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2544 format.cs.font_size = TRUE;
2545 format.cs.text_position = TRUE;
2546 format.cs.font = TRUE;
2547 format.font_size = new_index;
2548 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2550 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2551 GINT_TO_POINTER (new_index)))
2552 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2554 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2555 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2556 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2557 size_text, "</span>", NULL);
2559 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2563 gtk_widget_destroy (dialog);
2565 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2570 font_face_clicked (GtkToolButton *button,
2571 ModestMsgEditWindow *window)
2573 ModestMsgEditWindowPrivate *priv;
2574 GtkWidget *selector, *dialog;
2575 GtkCellRenderer *renderer;
2577 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2579 selector = hildon_touch_selector_new ();
2580 renderer = gtk_cell_renderer_text_new ();
2581 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2582 renderer, "family", 0, "text", 0, NULL);
2583 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2585 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2586 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2588 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2589 gint new_font_index;
2593 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2594 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2595 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2599 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2601 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2602 GINT_TO_POINTER(new_font_index)))
2603 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2605 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2606 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2608 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2612 gtk_tree_path_free (path);
2615 gtk_widget_destroy (dialog);
2617 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2622 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2625 ModestMsgEditWindowPrivate *priv = NULL;
2626 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2628 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2629 if (!priv->update_caption_visibility)
2632 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2634 gtk_widget_show (priv->cc_caption);
2636 gtk_widget_hide (priv->cc_caption);
2638 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2642 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2645 ModestMsgEditWindowPrivate *priv = NULL;
2646 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2648 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2649 if (!priv->update_caption_visibility)
2652 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2654 gtk_widget_show (priv->bcc_caption);
2656 gtk_widget_hide (priv->bcc_caption);
2658 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2662 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2663 ModestRecptEditor *editor)
2665 ModestMsgEditWindowPrivate *priv;
2667 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2668 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2670 /* we check for low-mem; in that case, show a warning, and don't allow
2671 * for the addressbook
2673 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2676 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2678 if (editor == NULL) {
2679 GtkWidget *view_focus;
2680 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2682 /* This code should be kept in sync with ModestRecptEditor. The
2683 textview inside the recpt editor is the one that really gets the
2684 focus. As it's inside a scrolled window, and this one inside the
2685 hbox recpt editor inherits from, we'll need to go up in the
2686 hierarchy to know if the text view is part of the recpt editor
2687 or if it's a different text entry */
2689 if (gtk_widget_get_parent (view_focus)) {
2690 GtkWidget *first_parent;
2692 first_parent = gtk_widget_get_parent (view_focus);
2693 if (gtk_widget_get_parent (first_parent) &&
2694 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2695 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2700 editor = MODEST_RECPT_EDITOR (priv->to_field);
2704 modest_address_book_select_addresses (editor);
2709 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2711 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2713 modest_msg_edit_window_open_addressbook (window, NULL);
2717 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2718 gboolean show_toolbar)
2720 ModestWindowPrivate *parent_priv;
2722 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2723 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2725 /* We can not just use the code of
2726 modest_msg_edit_window_setup_toolbar because it has a
2727 mixture of both initialization and creation code. */
2729 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2731 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2735 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2736 TnyHeaderFlags priority_flags)
2738 ModestMsgEditWindowPrivate *priv;
2739 ModestWindowPrivate *parent_priv;
2741 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2743 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2744 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2746 if (priv->priority_flags != priority_flags) {
2747 GtkAction *priority_action = NULL;
2749 priv->priority_flags = priority_flags;
2751 switch (priority_flags) {
2752 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2753 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2754 MODEST_HEADER_ICON_HIGH,
2755 HILDON_ICON_SIZE_SMALL);
2756 gtk_widget_show (priv->priority_icon);
2757 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2758 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2760 case TNY_HEADER_FLAG_LOW_PRIORITY:
2761 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2762 MODEST_HEADER_ICON_LOW,
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/MessagePriorityLowMenu");
2769 gtk_widget_hide (priv->priority_icon);
2770 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2771 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2774 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2775 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2777 gtk_widget_queue_resize (priv->subject_box);
2781 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2784 ModestMsgEditWindowPrivate *priv;
2785 ModestWindowPrivate *parent_priv;
2786 gint current_format;
2788 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2790 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2791 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2793 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2794 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2796 if (current_format != file_format) {
2797 switch (file_format) {
2798 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2799 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2800 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2802 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2806 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2807 response = gtk_dialog_run (GTK_DIALOG (dialog));
2808 gtk_widget_destroy (dialog);
2809 if (response == GTK_RESPONSE_OK) {
2810 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2812 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2813 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2818 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2819 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2820 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2825 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2828 ModestMsgEditWindowPrivate *priv;
2829 WPTextBufferFormat oldfmt, fmt;
2830 gint old_position = 0;
2834 GdkColor *color = NULL;
2835 gboolean bold, bold_set, italic, italic_set;
2836 gboolean underline, underline_set;
2837 gboolean strikethrough, strikethrough_set;
2838 gboolean position_set;
2839 gboolean font_size_set, font_set, color_set;
2842 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2843 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2845 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2846 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2847 GTK_WINDOW(dialog), GTK_WINDOW (window));
2849 /* First we get the currently selected font information */
2850 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2852 switch (oldfmt.text_position) {
2853 case TEXT_POSITION_NORMAL:
2856 case TEXT_POSITION_SUPERSCRIPT:
2864 g_object_set (G_OBJECT (dialog),
2865 "bold", oldfmt.bold != FALSE,
2866 "bold-set", !oldfmt.cs.bold,
2867 "underline", oldfmt.underline != FALSE,
2868 "underline-set", !oldfmt.cs.underline,
2869 "italic", oldfmt.italic != FALSE,
2870 "italic-set", !oldfmt.cs.italic,
2871 "strikethrough", oldfmt.strikethrough != FALSE,
2872 "strikethrough-set", !oldfmt.cs.strikethrough,
2873 "color", &oldfmt.color,
2874 "color-set", !oldfmt.cs.color,
2875 "size", wp_font_size[oldfmt.font_size],
2876 "size-set", !oldfmt.cs.font_size,
2877 "position", old_position,
2878 "position-set", !oldfmt.cs.text_position,
2879 "family", wp_get_font_name (oldfmt.font),
2880 "family-set", !oldfmt.cs.font,
2883 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2884 GTK_WINDOW (dialog), GTK_WINDOW (window));
2885 gtk_widget_show_all (dialog);
2886 priv->font_dialog = dialog;
2887 response = gtk_dialog_run (GTK_DIALOG (dialog));
2888 priv->font_dialog = NULL;
2889 if (response == GTK_RESPONSE_OK) {
2891 g_object_get( dialog,
2893 "bold-set", &bold_set,
2894 "underline", &underline,
2895 "underline-set", &underline_set,
2897 "italic-set", &italic_set,
2898 "strikethrough", &strikethrough,
2899 "strikethrough-set", &strikethrough_set,
2901 "color-set", &color_set,
2903 "size-set", &font_size_set,
2904 "family", &font_name,
2905 "family-set", &font_set,
2906 "position", &position,
2907 "position-set", &position_set,
2912 if (response == GTK_RESPONSE_OK) {
2913 memset(&fmt, 0, sizeof(fmt));
2919 fmt.italic = italic;
2920 fmt.cs.italic = TRUE;
2922 if (underline_set) {
2923 fmt.underline = underline;
2924 fmt.cs.underline = TRUE;
2926 if (strikethrough_set) {
2927 fmt.strikethrough = strikethrough;
2928 fmt.cs.strikethrough = TRUE;
2933 ? TEXT_POSITION_NORMAL
2934 : ( ( position == 1 )
2935 ? TEXT_POSITION_SUPERSCRIPT
2936 : TEXT_POSITION_SUBSCRIPT );
2937 fmt.cs.text_position = TRUE;
2938 fmt.font_size = oldfmt.font_size;
2942 fmt.cs.color = TRUE;
2945 fmt.font = wp_get_font_index(font_name,
2950 if (font_size_set) {
2951 fmt.cs.font_size = TRUE;
2952 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2954 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2955 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2957 gtk_widget_destroy (dialog);
2959 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2963 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2965 ModestMsgEditWindowPrivate *priv;
2967 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2968 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2970 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2972 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2973 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2977 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2979 ModestMsgEditWindowPrivate *priv;
2981 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2982 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2984 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2986 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2987 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2992 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2994 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2996 priv->can_undo = can_undo;
3000 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3002 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3004 priv->can_redo = can_redo;
3008 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3010 ModestMsgEditWindowPrivate *priv;
3011 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3012 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3014 return priv->can_undo;
3018 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3020 ModestMsgEditWindowPrivate *priv;
3021 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3022 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3024 return priv->can_redo;
3029 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3032 GtkTextIter match_start, match_end;
3034 if (image_id == NULL)
3037 gtk_text_buffer_get_start_iter (buffer, &iter);
3039 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3040 GSList *tags = gtk_text_iter_get_tags (&match_start);
3042 for (node = tags; node != NULL; node = g_slist_next (node)) {
3043 GtkTextTag *tag = (GtkTextTag *) node->data;
3044 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3045 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3046 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3048 offset = gtk_text_iter_get_offset (&match_start);
3049 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3050 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3054 gtk_text_iter_forward_char (&iter);
3059 message_is_empty (ModestMsgEditWindow *window)
3061 ModestMsgEditWindowPrivate *priv = NULL;
3063 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3064 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3066 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3067 * so we can ignore markup.
3069 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3072 count = gtk_text_buffer_get_char_count (buf);
3078 msg_body_focus (GtkWidget *focus,
3079 GdkEventFocus *event,
3083 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3084 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3085 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3090 recpt_field_changed (GtkTextBuffer *buffer,
3091 ModestMsgEditWindow *editor)
3093 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3094 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3098 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3100 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3101 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3105 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3108 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3109 GtkTextBuffer *buffer;
3111 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3112 gtk_text_buffer_set_modified (buffer, modified);
3113 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3114 gtk_text_buffer_set_modified (buffer, modified);
3115 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3116 gtk_text_buffer_set_modified (buffer, modified);
3117 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3121 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3123 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3124 const char *account_name;
3125 GtkTextBuffer *buffer;
3127 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3128 if (gtk_text_buffer_get_modified (buffer))
3130 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3131 if (gtk_text_buffer_get_modified (buffer))
3133 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3134 if (gtk_text_buffer_get_modified (buffer))
3136 if (gtk_text_buffer_get_modified (priv->text_buffer))
3138 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3139 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3150 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3152 ModestMsgEditWindowPrivate *priv = NULL;
3154 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3155 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3157 /* check if there's no recipient added */
3158 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3159 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3160 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3161 /* no recipient contents, then select contacts */
3162 modest_msg_edit_window_open_addressbook (window, NULL);
3166 g_object_ref (window);
3167 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3168 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3169 g_object_unref (window);
3172 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3173 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3174 g_object_unref (window);
3177 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3178 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3179 g_object_unref (window);
3183 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3184 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3185 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3186 g_object_unref (window);
3193 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3194 ModestMsgEditWindow *window)
3196 modest_msg_edit_window_offer_attach_file (window);
3200 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3202 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3204 return priv->clipboard_text;
3208 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3210 ModestMsgEditWindow *window)
3212 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3213 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3215 if (!GTK_WIDGET_VISIBLE (window))
3218 g_object_ref (window);
3219 text = gtk_clipboard_wait_for_text (selection_clipboard);
3221 if (priv->clipboard_text != NULL) {
3222 g_free (priv->clipboard_text);
3224 priv->clipboard_text = text;
3226 if (GTK_WIDGET_VISIBLE (window)) {
3227 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3229 g_object_unref (window);
3232 static gboolean clipboard_owner_change_idle (gpointer userdata)
3234 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3235 ModestMsgEditWindowPrivate *priv;
3237 gdk_threads_enter ();
3238 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3239 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3241 priv->clipboard_owner_idle = 0;
3242 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3243 gdk_threads_leave ();
3249 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3251 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3252 if (priv->clipboard_owner_idle == 0) {
3253 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3258 subject_field_move_cursor (GtkEntry *entry,
3259 GtkMovementStep step,
3264 if (!GTK_WIDGET_VISIBLE (window))
3267 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3271 update_window_title (ModestMsgEditWindow *window)
3273 ModestMsgEditWindowPrivate *priv = NULL;
3274 const gchar *subject;
3276 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3277 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3278 if (subject == NULL || subject[0] == '\0')
3279 subject = _("mail_va_new_email");
3281 gtk_window_set_title (GTK_WINDOW (window), subject);
3286 subject_field_changed (GtkEditable *editable,
3287 ModestMsgEditWindow *window)
3289 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3290 update_window_title (window);
3291 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3292 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3293 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3297 subject_field_insert_text (GtkEditable *editable,
3299 gint new_text_length,
3301 ModestMsgEditWindow *window)
3303 GString *result = g_string_new ("");
3305 gint result_len = 0;
3306 const gchar *entry_text = NULL;
3309 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3310 old_length = g_utf8_strlen (entry_text, -1);
3312 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3313 gunichar c = g_utf8_get_char_validated (current, 8);
3314 /* Invalid unichar, stop */
3320 result = g_string_append_unichar (result, c);
3324 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3325 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3328 /* Prevent endless recursion */
3329 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3330 g_signal_emit_by_name (editable, "insert-text",
3331 (gpointer) result->str, (gpointer) result->len,
3332 (gpointer) position, (gpointer) window);
3333 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3337 if (result_len + old_length > 1000) {
3338 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3339 _CS("ckdg_ib_maximum_characters_reached"));
3341 g_string_free (result, TRUE);
3345 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3348 ModestMsgEditWindowPrivate *priv = NULL;
3350 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3351 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3353 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3356 gtk_widget_show_all (priv->find_toolbar);
3357 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3359 gtk_widget_hide_all (priv->find_toolbar);
3360 gtk_widget_grab_focus (priv->msg_body);
3365 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3367 GtkTextIter *match_start,
3368 GtkTextIter *match_end)
3370 GtkTextIter end_iter;
3371 gchar *str_casefold;
3374 gchar *range_casefold;
3377 gboolean result = FALSE;
3384 gtk_text_iter_forward_to_end (&end_iter);
3386 str_casefold = g_utf8_casefold (str, -1);
3387 str_chars_n = strlen (str);
3389 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3390 range_casefold = g_utf8_casefold (range_text, -1);
3391 range_chars_n = strlen (range_casefold);
3393 if (range_chars_n < str_chars_n) {
3394 g_free (str_casefold);
3395 g_free (range_text);
3396 g_free (range_casefold);
3400 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3401 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3402 if (!g_utf8_collate (range_subtext, str_casefold)) {
3403 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3405 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3406 match_start, match_end, NULL);
3407 g_free (found_text);
3409 g_free (range_subtext);
3413 g_free (str_casefold);
3414 g_free (range_text);
3415 g_free (range_casefold);
3422 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3423 ModestMsgEditWindow *window)
3425 gchar *current_search = NULL;
3426 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3428 GtkTextIter selection_start, selection_end;
3429 GtkTextIter match_start, match_end;
3430 gboolean continue_search = FALSE;
3432 if (message_is_empty (window)) {
3433 g_free (priv->last_search);
3434 priv->last_search = NULL;
3435 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3439 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3440 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3441 g_free (current_search);
3442 g_free (priv->last_search);
3443 priv->last_search = NULL;
3444 /* Information banner about empty search */
3445 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3449 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3450 continue_search = TRUE;
3452 g_free (priv->last_search);
3453 priv->last_search = g_strdup (current_search);
3456 if (continue_search) {
3457 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3458 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3459 &match_start, &match_end);
3461 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3463 GtkTextIter buffer_start;
3464 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3465 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3466 &match_start, &match_end);
3468 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3471 /* Mark as selected the string found in search */
3473 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3474 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3475 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3477 g_free (priv->last_search);
3478 priv->last_search = NULL;
3480 g_free (current_search);
3484 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3486 ModestMsgEditWindowPrivate *priv;
3488 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3493 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3496 ModestMsgEditWindowPrivate *priv;
3498 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3503 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3504 ModestMsgEditWindow *window)
3506 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3510 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3513 ModestMsgEditWindowPrivate *priv;
3514 TnyHeader *header = NULL;
3516 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3517 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3519 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3520 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3522 if (priv->draft_msg != NULL) {
3523 g_object_unref (priv->draft_msg);
3526 if (draft != NULL) {
3527 g_object_ref (draft);
3528 header = tny_msg_get_header (draft);
3529 if (priv->msg_uid) {
3530 g_free (priv->msg_uid);
3531 priv->msg_uid = NULL;
3533 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3534 if (GTK_WIDGET_REALIZED (window)) {
3535 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3536 gtk_widget_destroy (GTK_WIDGET (window));
3542 priv->draft_msg = draft;
3546 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3547 GtkTextIter *start, GtkTextIter *end,
3550 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3551 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3554 if (tag == NULL) return;
3555 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3556 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3557 replace_with_images (window, priv->images);
3562 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3565 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3567 g_return_if_fail (TNY_IS_MIME_PART (part));
3568 tny_list_prepend (priv->attachments, (GObject *) part);
3569 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3570 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3571 gtk_widget_show_all (priv->attachments_caption);
3572 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3576 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3578 ModestMsgEditWindowPrivate *priv;
3580 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3581 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3583 return priv->msg_uid;
3587 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3588 ModestMsgEditWindowWidgetType widget_type)
3590 ModestMsgEditWindowPrivate *priv;
3592 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3593 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3595 switch (widget_type) {
3596 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3597 return priv->msg_body;
3599 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3600 return priv->to_field;
3602 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3603 return priv->cc_field;
3605 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3606 return priv->bcc_field;
3608 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3609 return priv->subject_field;
3611 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3612 return priv->attachments_view;
3620 remove_tags (WPTextBuffer *buffer)
3622 GtkTextIter start, end;
3624 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3625 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3627 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3631 on_account_removed (TnyAccountStore *account_store,
3632 TnyAccount *account,
3635 /* Do nothing if it's a store account, because we use the
3636 transport to send the messages */
3637 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3638 const gchar *parent_acc = NULL;
3639 const gchar *our_acc = NULL;
3641 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3642 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3643 /* Close this window if I'm showing a message of the removed account */
3644 if (strcmp (parent_acc, our_acc) == 0)
3645 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3650 from_field_changed (HildonPickerButton *button,
3651 ModestMsgEditWindow *self)
3653 ModestMsgEditWindowPrivate *priv;
3654 gboolean has_old_signature, has_new_signature;
3656 GtkTextIter match_start, match_end;
3657 ModestAccountMgr *mgr;
3659 gchar *full_signature;
3661 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3663 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3664 mgr = modest_runtime_get_account_mgr ();
3665 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3666 if (has_old_signature) {
3667 full_signature = g_strconcat ("\n--\n", signature, NULL);
3668 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3669 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3671 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3672 &match_start, &match_end, NULL)) {
3675 g_free (full_signature);
3679 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3680 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3681 if (has_new_signature) {
3682 full_signature = g_strconcat ("\n--\n", signature, NULL);
3683 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3684 g_free (full_signature);
3689 typedef struct _MessageSettingsHelper {
3690 ModestMsgEditWindow *window;
3691 GSList *priority_group;
3692 GSList *format_group;
3693 GtkToggleButton *current_priority;
3694 GtkToggleButton *current_format;
3695 } MessageSettingsHelper;
3698 on_priority_toggle (GtkToggleButton *button,
3699 MessageSettingsHelper *helper)
3702 ModestMsgEditWindowPrivate *priv;
3704 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3705 if (gtk_toggle_button_get_active (button)) {
3707 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3708 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3709 if ((node_button != button) &&
3710 gtk_toggle_button_get_active (node_button)) {
3711 gtk_toggle_button_set_active (node_button, FALSE);
3714 helper->current_priority = button;
3716 gboolean found = FALSE;
3717 /* If no one is active, activate it again */
3718 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3719 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3720 if (gtk_toggle_button_get_active (node_button)) {
3726 gtk_toggle_button_set_active (button, TRUE);
3732 on_format_toggle (GtkToggleButton *button,
3733 MessageSettingsHelper *helper)
3736 ModestMsgEditWindowPrivate *priv;
3738 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3739 if (gtk_toggle_button_get_active (button)) {
3741 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3742 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3743 if ((node_button != button) &&
3744 gtk_toggle_button_get_active (node_button)) {
3745 gtk_toggle_button_set_active (node_button, FALSE);
3748 helper->current_format = button;
3750 gboolean found = FALSE;
3751 /* If no one is active, activate it again */
3752 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3753 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3754 if (gtk_toggle_button_get_active (node_button)) {
3760 gtk_toggle_button_set_active (button, TRUE);
3767 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3772 GtkWidget *priority_hbox;
3773 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3774 GtkWidget *captioned;
3775 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3776 GtkWidget *format_hbox;
3777 GtkWidget *html_toggle, *text_toggle;
3778 ModestMsgEditWindowPrivate *priv;
3779 MessageSettingsHelper helper = {0,};
3781 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3782 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3783 helper.window = window;
3784 helper.priority_group = NULL;
3785 helper.format_group = NULL;
3787 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3788 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3790 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3791 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3792 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3793 vbox = gtk_vbox_new (FALSE, 0);
3794 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
3795 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
3796 gtk_container_add (GTK_CONTAINER (align), vbox);
3797 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
3798 gtk_widget_show (align);
3799 gtk_widget_show (vbox);
3801 /* Priority toggles */
3802 priority_hbox = gtk_hbox_new (TRUE, 0);
3803 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3804 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3805 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3806 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3807 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3808 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3809 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3810 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3811 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3812 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3813 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3814 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3815 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3816 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3817 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3818 gtk_widget_show_all (priority_hbox);
3819 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3820 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3821 gtk_widget_show (captioned);
3822 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3824 /* format toggles */
3825 format_hbox = gtk_hbox_new (TRUE, 0);
3826 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3827 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3828 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3829 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3830 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3831 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3832 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3833 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3834 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3835 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3836 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3837 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3838 gtk_widget_show_all (format_hbox);
3839 gtk_widget_show (format_hbox);
3840 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3843 g_object_unref (title_sizegroup);
3844 g_object_unref (value_sizegroup);
3846 /* Set current values */
3847 switch (priv->priority_flags) {
3848 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3849 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3850 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3852 case TNY_HEADER_FLAG_LOW_PRIORITY:
3853 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3854 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3857 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3858 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3862 switch (modest_msg_edit_window_get_format (window)) {
3863 case MODEST_MSG_EDIT_FORMAT_TEXT:
3864 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3865 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3867 case MODEST_MSG_EDIT_FORMAT_HTML:
3869 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3870 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3874 /* Signal connects */
3875 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3876 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3877 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3878 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3879 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3881 /* Save settings if the user clicked on done */
3882 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3883 TnyHeaderFlags flags;
3884 ModestMsgEditFormat old_format, new_format;
3886 /* Set priority flags */
3887 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3888 if (priv->priority_flags != flags)
3889 modest_msg_edit_window_set_priority_flags (window, flags);
3891 /* Set edit format */
3892 old_format = modest_msg_edit_window_get_format (window);
3893 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3894 if (old_format != new_format) {
3895 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3896 modest_msg_edit_window_set_file_format (window, file_format);
3900 gtk_widget_destroy (dialog);
3901 g_slist_free (helper.priority_group);
3905 on_message_settings (GtkAction *action,
3906 ModestMsgEditWindow *window)
3908 modest_msg_edit_window_show_msg_settings_dialog (window);
3912 on_cc_button_toggled (HildonCheckButton *button,
3913 ModestMsgEditWindow *window)
3915 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3917 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3918 hildon_check_button_get_active (button));
3922 on_bcc_button_toggled (HildonCheckButton *button,
3923 ModestMsgEditWindow *window)
3925 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3927 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3928 hildon_check_button_get_active (button));
3932 setup_menu (ModestMsgEditWindow *self)
3934 ModestMsgEditWindowPrivate *priv = NULL;
3936 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3938 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3940 /* Settings menu buttons */
3941 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3942 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3944 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3945 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3946 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3948 priv->cc_button = hildon_check_button_new (0);
3949 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3950 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3952 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3954 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3955 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3956 priv->bcc_button = hildon_check_button_new (0);
3957 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3958 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3960 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3962 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3963 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3965 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3966 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3967 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3968 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3969 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3970 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3971 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3972 APP_MENU_CALLBACK (on_message_settings),
3974 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
3975 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),