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_font_change (GtkCheckMenuItem *menu_item,
122 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
124 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
125 ModestRecptEditor *editor);
126 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
127 ModestMsgEditWindow *window);
129 /* ModestWindow methods implementation */
130 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
131 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
132 gboolean show_toolbar);
133 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
135 ModestMsgEditWindow *window);
136 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
137 static void subject_field_move_cursor (GtkEntry *entry,
138 GtkMovementStep step,
142 static void update_window_title (ModestMsgEditWindow *window);
145 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
146 ModestMsgEditWindow *window);
147 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
148 ModestMsgEditWindow *window);
149 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
151 GtkTextIter *match_start,
152 GtkTextIter *match_end);
154 static void remove_tags (WPTextBuffer *buffer);
156 static void on_account_removed (TnyAccountStore *account_store,
160 static void init_window (ModestMsgEditWindow *obj);
162 gboolean scroll_drag_timeout (gpointer userdata);
163 static void correct_scroll (ModestMsgEditWindow *w);
164 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
165 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
166 ModestMsgEditWindow *userdata);
167 static void text_buffer_mark_set (GtkTextBuffer *buffer,
170 ModestMsgEditWindow *userdata);
171 static void on_message_settings (GtkAction *action,
172 ModestMsgEditWindow *window);
173 static void setup_menu (ModestMsgEditWindow *self);
175 static void from_field_changed (HildonPickerButton *button,
176 ModestMsgEditWindow *self);
177 static void font_size_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 GtkWidget *font_tool_button_label;
267 GtkTreeModel *sizes_model;
268 gint current_size_index;
269 GtkWidget *size_tool_button_label;
271 GtkWidget *find_toolbar;
274 GtkWidget *font_dialog;
277 guint correct_scroll_idle;
278 guint scroll_drag_timeout_id;
282 TnyList *attachments;
287 TnyHeaderFlags priority_flags;
289 gboolean can_undo, can_redo;
290 gulong clipboard_change_handler_id;
291 gulong default_clipboard_change_handler_id;
292 gulong account_removed_handler_id;
293 guint clipboard_owner_idle;
294 gchar *clipboard_text;
303 GtkWidget *cc_button;
304 GtkWidget *bcc_button;
307 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
308 MODEST_TYPE_MSG_EDIT_WINDOW, \
309 ModestMsgEditWindowPrivate))
311 static GtkWindowClass *parent_class = NULL;
313 /* uncomment the following if you have defined any signals */
314 /* static guint signals[LAST_SIGNAL] = {0}; */
317 modest_msg_edit_window_get_type (void)
319 static GType my_type = 0;
321 static const GTypeInfo my_info = {
322 sizeof(ModestMsgEditWindowClass),
323 NULL, /* base init */
324 NULL, /* base finalize */
325 (GClassInitFunc) modest_msg_edit_window_class_init,
326 NULL, /* class finalize */
327 NULL, /* class data */
328 sizeof(ModestMsgEditWindow),
330 (GInstanceInitFunc) modest_msg_edit_window_init,
333 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
334 "ModestMsgEditWindow",
342 save_state (ModestWindow *self)
344 modest_widget_memory_save (modest_runtime_get_conf(),
345 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
350 restore_settings (ModestMsgEditWindow *self)
352 ModestConf *conf = NULL;
354 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
356 conf = modest_runtime_get_conf ();
358 /* Dim at start clipboard actions */
359 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
360 gtk_action_set_sensitive (action, FALSE);
361 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
362 gtk_action_set_sensitive (action, FALSE);
363 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
364 gtk_action_set_sensitive (action, FALSE);
366 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
371 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
373 GObjectClass *gobject_class;
374 ModestWindowClass *modest_window_class;
375 gobject_class = (GObjectClass*) klass;
376 modest_window_class = (ModestWindowClass*) klass;
378 parent_class = g_type_class_peek_parent (klass);
379 gobject_class->finalize = modest_msg_edit_window_finalize;
381 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
382 modest_window_class->save_state_func = save_state;
383 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
385 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
389 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
391 ModestMsgEditWindowPrivate *priv;
392 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
394 priv->msg_body = NULL;
395 priv->from_field = NULL;
396 priv->to_field = NULL;
397 priv->cc_field = NULL;
398 priv->bcc_field = NULL;
399 priv->subject_field = NULL;
400 priv->attachments = TNY_LIST (tny_simple_list_new ());
401 priv->images = TNY_LIST (tny_simple_list_new ());
402 priv->images_size = 0;
403 priv->images_count = 0;
406 priv->cc_caption = NULL;
407 priv->bcc_caption = NULL;
408 priv->update_caption_visibility = FALSE;
410 priv->priority_flags = 0;
412 priv->find_toolbar = NULL;
413 priv->last_search = NULL;
415 priv->draft_msg = NULL;
416 priv->outbox_msg = NULL;
417 priv->msg_uid = NULL;
419 priv->can_undo = FALSE;
420 priv->can_redo = FALSE;
421 priv->clipboard_change_handler_id = 0;
422 priv->default_clipboard_change_handler_id = 0;
423 priv->account_removed_handler_id = 0;
424 priv->clipboard_owner_idle = 0;
425 priv->clipboard_text = NULL;
428 priv->scroll_drag_timeout_id = 0;
429 priv->correct_scroll_idle = 0;
430 priv->last_upper = 0.0;
432 priv->font_dialog = NULL;
433 priv->app_menu = NULL;
435 if (!is_wp_text_buffer_started) {
436 is_wp_text_buffer_started = TRUE;
437 wp_text_buffer_library_init ();
442 hildon_program_add_window (hildon_program_get_instance(),
448 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
450 static ModestPairList*
451 get_transports (void)
453 GSList *transports = NULL;
455 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
456 GSList *accounts = modest_account_mgr_account_names (account_mgr,
457 TRUE /* only enabled accounts. */);
459 GSList *cursor = accounts;
461 gchar *account_name = cursor->data;
462 gchar *from_string = NULL;
464 from_string = modest_account_mgr_get_from_string (account_mgr,
468 if (from_string && account_name) {
469 gchar *name = account_name;
470 ModestPair *pair = modest_pair_new ((gpointer) name,
471 (gpointer) from_string , TRUE);
472 transports = g_slist_prepend (transports, pair);
475 cursor = cursor->next;
477 g_slist_free (accounts); /* only free the accounts, not the elements,
478 * because they are used in the pairlist */
482 static void window_focus (GtkWindow *window,
486 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
490 scroll_drag_timeout (gpointer userdata)
492 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
493 ModestMsgEditWindowPrivate *priv;
495 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
497 correct_scroll_without_drag_check (win, TRUE);
499 priv->scroll_drag_timeout_id = 0;
505 correct_scroll_without_drag_check_idle (gpointer userdata)
507 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
508 ModestMsgEditWindowPrivate *priv;
510 GdkRectangle rectangle;
511 gint offset_min, offset_max;
515 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
517 insert = gtk_text_buffer_get_insert (priv->text_buffer);
518 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
520 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
521 offset_min = priv->msg_body->allocation.y + rectangle.y;
522 offset_max = offset_min + rectangle.height;
524 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
525 offset_min = MAX (offset_min - 48, 0);
526 offset_max = MIN (offset_max + 48, vadj->upper);
528 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
530 priv->correct_scroll_idle = 0;
535 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
537 ModestMsgEditWindowPrivate *priv;
539 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
541 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
544 if (priv->correct_scroll_idle > 0) {
548 priv->correct_scroll_idle = g_idle_add ((GSourceFunc) correct_scroll_without_drag_check_idle,
553 correct_scroll (ModestMsgEditWindow *w)
555 ModestMsgEditWindowPrivate *priv;
557 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
558 if (gtk_grab_get_current () == priv->msg_body) {
559 if (priv->scroll_drag_timeout_id == 0) {
560 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
566 correct_scroll_without_drag_check (w, TRUE);
570 text_buffer_end_user_action (GtkTextBuffer *buffer,
571 ModestMsgEditWindow *userdata)
574 correct_scroll (userdata);
578 text_buffer_mark_set (GtkTextBuffer *buffer,
581 ModestMsgEditWindow *userdata)
583 gtk_text_buffer_begin_user_action (buffer);
584 gtk_text_buffer_end_user_action (buffer);
588 cut_clipboard_check (GtkTextView *text_view,
591 GtkTextBuffer *buffer;
593 buffer = gtk_text_view_get_buffer (text_view);
594 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
595 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
600 copy_clipboard_check (GtkTextView *text_view,
603 GtkTextBuffer *buffer;
605 buffer = gtk_text_view_get_buffer (text_view);
606 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
607 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
612 attachment_deleted (ModestAttachmentsView *attachments_view,
615 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
620 connect_signals (ModestMsgEditWindow *obj)
622 ModestMsgEditWindowPrivate *priv;
624 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
626 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
627 G_CALLBACK (text_buffer_refresh_attributes), obj);
628 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
629 G_CALLBACK (text_buffer_can_undo), obj);
630 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
631 G_CALLBACK (text_buffer_can_redo), obj);
632 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
633 G_CALLBACK (body_changed), obj);
634 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
635 G_CALLBACK (body_changed), obj);
636 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
637 G_CALLBACK (text_buffer_end_user_action), obj);
638 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
639 G_CALLBACK (text_buffer_mark_set), obj);
640 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
641 G_CALLBACK (text_buffer_apply_tag), obj);
642 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
643 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
644 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
645 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
646 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
647 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
649 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
650 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
651 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
652 G_CALLBACK (from_field_changed), obj);
654 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
655 G_CALLBACK (msg_body_focus), obj);
656 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
657 G_CALLBACK (msg_body_focus), obj);
658 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
659 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
660 "changed", G_CALLBACK (recpt_field_changed), obj);
661 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
662 "changed", G_CALLBACK (recpt_field_changed), obj);
663 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
664 "changed", G_CALLBACK (recpt_field_changed), obj);
665 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
666 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
667 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
669 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
670 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
672 priv->clipboard_change_handler_id =
673 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
674 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
675 priv->default_clipboard_change_handler_id =
676 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
677 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
679 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
680 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
681 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
685 init_wp_text_view_style ()
687 static gboolean initialized = FALSE;
690 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
696 init_window (ModestMsgEditWindow *obj)
698 GtkWidget *to_caption, *subject_caption;
699 GtkWidget *main_vbox;
700 GtkWidget *add_attachment_align;
701 ModestMsgEditWindowPrivate *priv;
702 GtkActionGroup *action_group;
703 ModestWindowPrivate *parent_priv;
704 GdkPixbuf *window_icon = NULL;
705 GError *error = NULL;
707 GtkSizeGroup *title_size_group;
708 GtkSizeGroup *value_size_group;
709 GtkWidget *attachment_icon;
710 GtkWidget *window_box;
711 GtkWidget *window_align;
712 #if (GTK_MINOR_VERSION >= 10)
713 GdkAtom deserialize_type;
716 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
717 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
719 parent_priv->ui_manager = gtk_ui_manager_new();
720 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
721 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
723 /* Add common actions */
724 gtk_action_group_add_actions (action_group,
725 modest_msg_edit_action_entries,
726 G_N_ELEMENTS (modest_msg_edit_action_entries),
728 gtk_action_group_add_actions (action_group,
729 hildon2_msg_edit_action_entries,
730 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
732 gtk_action_group_add_toggle_actions (action_group,
733 modest_msg_edit_toggle_action_entries,
734 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
736 gtk_action_group_add_radio_actions (action_group,
737 modest_msg_edit_alignment_radio_action_entries,
738 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
740 G_CALLBACK (modest_ui_actions_on_change_justify),
742 gtk_action_group_add_radio_actions (action_group,
743 modest_msg_edit_priority_action_entries,
744 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
746 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
748 gtk_action_group_add_radio_actions (action_group,
749 modest_msg_edit_file_format_action_entries,
750 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
751 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
752 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
754 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
755 g_object_unref (action_group);
757 /* Load the UI definition */
758 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
761 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
762 g_clear_error (&error);
765 /* Add accelerators */
766 gtk_window_add_accel_group (GTK_WINDOW (obj),
767 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
769 parent_priv->menubar = NULL;
771 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
772 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
774 /* Note: This ModestPairList* must exist for as long as the picker
775 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
776 * so it can't know how to manage its memory. */
777 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
778 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
780 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
781 _("mail_va_from"), priv->from_field);
783 priv->to_field = modest_recpt_editor_new ();
784 priv->cc_field = modest_recpt_editor_new ();
785 priv->bcc_field = modest_recpt_editor_new ();
786 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
787 priv->priority_icon = gtk_image_new ();
788 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
789 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
790 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
791 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
792 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
793 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
794 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
795 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
796 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
797 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
798 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
799 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
800 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
801 add_attachment_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
802 gtk_alignment_set_padding (GTK_ALIGNMENT (add_attachment_align), 0, 0, MODEST_MARGIN_DEFAULT, 0);
803 gtk_container_add (GTK_CONTAINER (add_attachment_align), priv->add_attachment_button);
804 gtk_box_pack_start (GTK_BOX (priv->subject_box), add_attachment_align, FALSE, FALSE, 0);
805 priv->attachments_view = modest_attachments_view_new (NULL);
806 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
807 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
809 priv->header_box = gtk_vbox_new (FALSE, 0);
811 to_caption = modest_maemo_utils_create_captioned_with_size_type
812 (title_size_group, value_size_group,
813 _("mail_va_to"), FALSE, priv->to_field,
814 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
815 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
816 (title_size_group, value_size_group,
817 _("mail_va_cc"), FALSE, priv->cc_field,
818 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
819 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
820 (title_size_group, value_size_group,
821 _("mail_va_hotfix1"), FALSE, priv->bcc_field,
822 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
823 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
824 _("mail_va_subject"), FALSE, priv->subject_box);
825 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
826 _("mail_va_attachment"),
828 priv->attachments_view,
829 HILDON_SIZE_AUTO_WIDTH |
830 HILDON_SIZE_AUTO_HEIGHT);
831 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
832 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
833 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
834 g_object_unref (title_size_group);
835 g_object_unref (value_size_group);
837 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
838 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
839 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
840 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
841 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
842 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
843 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
845 init_wp_text_view_style ();
847 priv->msg_body = modest_wp_text_view_new ();
850 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
851 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
852 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
853 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
854 #if (GTK_MINOR_VERSION >= 10)
855 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
856 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
858 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
859 deserialize_type, TRUE);
861 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
863 priv->find_toolbar = hildon_find_toolbar_new (NULL);
864 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
866 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
868 priv->pannable = hildon_pannable_area_new ();
870 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
871 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
872 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
874 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
875 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
876 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
878 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
879 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox),
880 hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable)));
881 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
883 window_box = gtk_vbox_new (FALSE, 0);
884 gtk_container_add (GTK_CONTAINER(obj), window_box);
886 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
888 /* Set window icon */
889 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
891 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
892 g_object_unref (window_icon);
897 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
899 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
901 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
902 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
903 priv->clipboard_change_handler_id))
904 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
905 priv->clipboard_change_handler_id);
906 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
907 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
908 priv->default_clipboard_change_handler_id))
909 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
910 priv->default_clipboard_change_handler_id);
912 if (priv->account_removed_handler_id &&
913 g_signal_handler_is_connected (modest_runtime_get_account_store (),
914 priv->account_removed_handler_id))
915 g_signal_handler_disconnect(modest_runtime_get_account_store (),
916 priv->account_removed_handler_id);
920 modest_msg_edit_window_finalize (GObject *obj)
922 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
924 /* Sanity check: shouldn't be needed, the window mgr should
925 call this function before */
926 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
928 if (priv->font_dialog != NULL) {
929 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
932 if (priv->clipboard_text != NULL) {
933 g_free (priv->clipboard_text);
934 priv->clipboard_text = NULL;
937 if (priv->draft_msg != NULL) {
938 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
939 if (TNY_IS_HEADER (header)) {
940 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
941 modest_window_mgr_unregister_header (mgr, header);
943 g_object_unref (priv->draft_msg);
944 priv->draft_msg = NULL;
946 if (priv->outbox_msg != NULL) {
947 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
948 if (TNY_IS_HEADER (header)) {
949 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
950 modest_window_mgr_unregister_header (mgr, header);
952 g_object_unref (priv->outbox_msg);
953 priv->outbox_msg = NULL;
955 if (priv->correct_scroll_idle > 0) {
956 g_source_remove (priv->correct_scroll_idle);
957 priv->correct_scroll_idle = 0;
959 if (priv->scroll_drag_timeout_id > 0) {
960 g_source_remove (priv->scroll_drag_timeout_id);
961 priv->scroll_drag_timeout_id = 0;
963 if (priv->clipboard_owner_idle > 0) {
964 g_source_remove (priv->clipboard_owner_idle);
965 priv->clipboard_owner_idle = 0;
967 if (priv->original_account_name)
968 g_free (priv->original_account_name);
969 g_free (priv->msg_uid);
970 g_free (priv->last_search);
971 g_slist_free (priv->font_items_group);
972 g_object_unref (priv->sizes_model);
973 g_object_unref (priv->attachments);
974 g_object_unref (priv->images);
976 /* This had to stay alive for as long as the picker that used it: */
977 modest_pair_list_free (priv->from_field_protos);
979 G_OBJECT_CLASS(parent_class)->finalize (obj);
983 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
985 GdkPixbufLoader *loader;
991 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
993 if (loader == NULL) {
999 tny_stream_reset (TNY_STREAM (stream));
1000 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1001 GError *error = NULL;
1002 unsigned char read_buffer[128];
1004 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1006 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1008 g_error_free (error);
1013 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1015 g_object_ref (pixbuf);
1016 gdk_pixbuf_loader_close (loader, NULL);
1017 g_object_unref (loader);
1022 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1023 GdkPixbuf *new_pixbuf;
1025 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1026 gdk_pixbuf_get_width (pixbuf);
1027 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1028 g_object_unref (pixbuf);
1029 pixbuf = new_pixbuf;
1033 *stream_size = size;
1039 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1041 ModestMsgEditWindowPrivate *priv;
1044 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1046 for (iter = tny_list_create_iterator (attachments);
1047 !tny_iterator_is_done (iter);
1048 tny_iterator_next (iter)) {
1049 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1050 const gchar *cid = tny_mime_part_get_content_id (part);
1051 const gchar *mime_type = tny_mime_part_get_content_type (part);
1052 if ((cid != NULL)&&(mime_type != NULL)) {
1053 guint64 stream_size;
1054 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1055 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1058 g_object_unref (stream);
1060 if (pixbuf != NULL) {
1061 priv->images_count ++;
1062 priv->images_size += stream_size;
1063 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1064 g_object_unref (pixbuf);
1067 g_object_unref (part);
1069 g_object_unref (iter);
1073 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1075 TnyMimePart *parent = NULL;
1076 const gchar *content_type = NULL;
1077 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1079 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1081 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1082 parent = g_object_ref (msg);
1083 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1084 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1087 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1088 iter = tny_list_create_iterator (parts);
1089 while (!tny_iterator_is_done (iter)) {
1091 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1092 content_type = tny_mime_part_get_content_type (part);
1093 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1097 g_object_unref (part);
1099 tny_iterator_next (iter);
1101 g_object_unref (iter);
1102 g_object_unref (parts);
1105 if (parent != NULL) {
1106 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1109 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1110 iter = tny_list_create_iterator (parts);
1111 while (!tny_iterator_is_done (iter)) {
1113 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1114 content_type = tny_mime_part_get_content_type (part);
1115 if (content_type && g_str_has_prefix (content_type, "image/")) {
1116 tny_list_prepend (priv->images, (GObject *) part);
1118 g_object_unref (part);
1119 tny_iterator_next (iter);
1121 g_object_unref (iter);
1122 g_object_unref (parts);
1123 g_object_unref (parent);
1128 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1131 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1133 for (iter = tny_list_create_iterator (attachments) ;
1134 !tny_iterator_is_done (iter);
1135 tny_iterator_next (iter)) {
1136 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1137 const gchar *cid = tny_mime_part_get_content_id (part);
1139 char *invalid = NULL;
1140 gint int_cid = strtol (cid, &invalid, 10);
1141 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1142 priv->next_cid = int_cid + 1;
1145 g_object_unref (part);
1147 g_object_unref (iter);
1151 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1154 gchar *to, *cc, *bcc, *subject;
1156 ModestMsgEditWindowPrivate *priv;
1157 ModestWindowPrivate *parent_priv;
1159 TnyHeaderFlags priority_flags;
1160 TnyFolder *msg_folder;
1161 gboolean is_html = FALSE;
1162 gboolean field_view_set;
1164 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1165 g_return_if_fail (TNY_IS_MSG (msg));
1167 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1168 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1170 header = tny_msg_get_header (msg);
1171 to = tny_header_dup_to (header);
1172 cc = tny_header_dup_cc (header);
1173 bcc = tny_header_dup_bcc (header);
1174 subject = tny_header_dup_subject (header);
1175 priority_flags = tny_header_get_priority (header);
1178 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1180 field_view_set = TRUE;
1182 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1183 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1184 gtk_widget_show (priv->cc_caption);
1185 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1186 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1187 gtk_widget_hide (priv->cc_caption);
1188 field_view_set = FALSE;
1190 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1192 field_view_set = TRUE;
1194 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1195 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1196 gtk_widget_show (priv->bcc_caption);
1197 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1198 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1199 gtk_widget_hide (priv->bcc_caption);
1200 field_view_set = FALSE;
1202 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1206 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1207 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1210 update_window_title (self);
1212 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1213 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1215 if ((body == NULL)||(body[0] == '\0')) {
1217 body = modest_text_utils_convert_to_html ("");
1220 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1221 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1224 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1227 /* Add attachments to the view */
1228 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1229 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1230 if (tny_list_get_length (priv->attachments) == 0) {
1231 gtk_widget_hide (priv->attachments_caption);
1233 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1234 gtk_widget_show_all (priv->attachments_caption);
1236 get_related_images (self, msg);
1237 update_next_cid (self, priv->attachments);
1238 update_next_cid (self, priv->images);
1239 replace_with_images (self, priv->images);
1241 if (preserve_is_rich && !is_html) {
1242 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1243 /* Get the default format required from configuration */
1244 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1245 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1248 /* Set the default focus depending on having already a To: field or not */
1249 if ((!to)||(*to == '\0')) {
1250 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1252 gtk_widget_grab_focus (priv->msg_body);
1255 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1257 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1258 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1260 modest_msg_edit_window_set_modified (self, FALSE);
1262 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1263 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1264 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1265 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1267 if (priv->msg_uid) {
1268 g_free (priv->msg_uid);
1269 priv->msg_uid = NULL;
1272 /* we should set a reference to the incoming message if it is a draft */
1273 msg_folder = tny_msg_get_folder (msg);
1275 if (modest_tny_folder_is_local_folder (msg_folder)) {
1276 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1277 if (type == TNY_FOLDER_TYPE_INVALID)
1278 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1280 if (type == TNY_FOLDER_TYPE_DRAFTS)
1281 priv->draft_msg = g_object_ref(msg);
1282 if (type == TNY_FOLDER_TYPE_OUTBOX)
1283 priv->outbox_msg = g_object_ref(msg);
1284 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1286 g_object_unref (msg_folder);
1296 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1299 GList *item_children, *node;
1300 GtkWidget *bin_child;
1302 bin_child = gtk_bin_get_child (GTK_BIN(item));
1304 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1306 for (node = item_children; node != NULL; node = g_list_next (node)) {
1307 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1308 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1311 g_list_free (item_children);
1315 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1318 GList *item_children, *node;
1320 box = gtk_bin_get_child (GTK_BIN (item));
1321 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1322 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1324 for (node = item_children; node != NULL; node = g_list_next (node)) {
1325 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1326 if (GTK_IS_TOGGLE_BUTTON (node->data))
1327 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1328 else if (GTK_IS_BUTTON (node->data))
1329 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1331 g_list_free (item_children);
1336 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1338 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1339 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1340 GtkWidget *placeholder;
1341 GtkWidget *tool_item;
1346 GtkWidget *sizes_menu;
1347 GtkWidget *fonts_menu;
1348 GSList *radio_group = NULL;
1349 GSList *node = NULL;
1353 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1354 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1355 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1356 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1358 /* Font color placeholder */
1359 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1360 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1363 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1364 priv->font_color_button = hildon_color_button_new ();
1365 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1366 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1367 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1368 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1369 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1370 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1371 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1372 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1374 G_CALLBACK (modest_msg_edit_window_color_button_change),
1377 /* Font size and face placeholder */
1378 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1379 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1381 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1382 priv->size_tool_button_label = gtk_label_new (NULL);
1383 hildon_helper_set_logical_color (GTK_WIDGET (priv->size_tool_button_label), GTK_RC_TEXT,
1384 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1385 hildon_helper_set_logical_color (GTK_WIDGET (priv->size_tool_button_label), GTK_RC_FG,
1386 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1387 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1388 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1389 size_text,"</span>", NULL);
1390 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1392 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1393 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1394 sizes_menu = gtk_menu_new ();
1395 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1396 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1399 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1400 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1402 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1406 if (wp_font_size[size_index] == 12)
1407 priv->current_size_index = size_index;
1411 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1412 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1413 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), FALSE);
1414 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), FALSE);
1415 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1416 priv->font_size_toolitem = tool_item;
1419 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1420 priv->font_tool_button_label = gtk_label_new (NULL);
1421 hildon_helper_set_logical_color (GTK_WIDGET (priv->font_tool_button_label), GTK_RC_TEXT,
1422 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1423 hildon_helper_set_logical_color (GTK_WIDGET (priv->font_tool_button_label), GTK_RC_FG,
1424 GTK_STATE_INSENSITIVE, "SecondaryTextColor");
1425 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1426 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1428 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1429 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1430 fonts_menu = gtk_menu_new ();
1431 priv->font_items_group = NULL;
1433 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1434 GtkWidget *font_menu_item;
1435 GtkWidget *child_label;
1437 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1438 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1439 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1440 wp_get_font_name (font_index), "</span>", NULL);
1441 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1444 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1445 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1446 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1447 gtk_widget_show (font_menu_item);
1449 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1452 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1453 GtkWidget *item = (GtkWidget *) node->data;
1454 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1457 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1458 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1459 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1460 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1461 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), FALSE);
1462 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), FALSE);
1463 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1464 priv->font_face_toolitem = tool_item;
1466 /* Set expand and homogeneous for remaining items */
1467 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1468 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1469 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1470 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1471 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1472 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1473 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1474 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1475 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1477 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1478 will not show the tool items added to the placeholders) */
1479 gtk_widget_show_all (parent_priv->toolbar);
1481 /* Set the no show all *after* showing all items. We do not
1482 want the toolbar to be shown with a show all because it
1483 could go agains the gconf setting regarding showing or not
1484 the toolbar of the editor window */
1485 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1491 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1494 ModestWindowPrivate *parent_priv;
1495 ModestMsgEditWindowPrivate *priv;
1496 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1497 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1498 ModestWindowMgr *mgr = NULL;
1500 g_return_val_if_fail (msg, NULL);
1501 g_return_val_if_fail (account_name, NULL);
1503 mgr = modest_runtime_get_window_mgr ();
1505 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1507 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1508 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1510 /* Menubar. Update the state of some toggles */
1511 priv->from_field_protos = get_transports ();
1512 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1513 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1514 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1515 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1517 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1518 hildon_touch_selector_get_current_text
1519 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1520 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1521 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1524 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1526 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1528 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1530 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1532 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1533 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1534 /* Add common dimming rules */
1535 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1536 modest_msg_edit_window_toolbar_dimming_entries,
1537 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1538 MODEST_WINDOW (obj));
1539 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1540 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1541 MODEST_WINDOW (obj));
1542 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1543 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1544 MODEST_WINDOW (obj));
1545 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1546 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1547 MODEST_WINDOW (obj));
1548 /* Insert dimming rules group for this window */
1549 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1550 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1552 /* Setup app menu */
1553 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1555 /* Checks the dimming rules */
1556 g_object_unref (toolbar_rules_group);
1557 g_object_unref (clipboard_rules_group);
1558 gtk_widget_hide (priv->priority_icon);
1559 gtk_widget_queue_resize (priv->subject_box);
1560 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1562 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1564 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1565 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1566 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1567 priv->update_caption_visibility = TRUE;
1569 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1571 /* Track account-removed signal, this window should be closed
1572 in the case we're creating a mail associated to the account
1574 priv->account_removed_handler_id =
1575 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1577 G_CALLBACK(on_account_removed),
1580 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1582 return (ModestWindow*) obj;
1586 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1588 GString **string_buffer = (GString **) user_data;
1590 *string_buffer = g_string_append (*string_buffer, buffer);
1596 * @result: A new string which should be freed with g_free().
1599 get_formatted_data (ModestMsgEditWindow *edit_window)
1601 ModestMsgEditWindowPrivate *priv;
1602 GString *string_buffer = g_string_new ("");
1604 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1606 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1608 modest_text_utils_hyperlinkify (string_buffer);
1610 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1612 return g_string_free (string_buffer, FALSE);
1617 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1620 const gchar *account_name;
1621 ModestMsgEditWindowPrivate *priv;
1622 TnyIterator *att_iter;
1624 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1626 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1628 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1629 g_return_val_if_fail (account_name, NULL);
1632 /* don't free these (except from) */
1633 data = g_slice_new0 (MsgData);
1634 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1636 data->account_name = g_strdup (account_name);
1637 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1638 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1639 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1640 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1641 if (priv->draft_msg) {
1642 data->draft_msg = g_object_ref (priv->draft_msg);
1643 } else if (priv->outbox_msg) {
1644 data->draft_msg = g_object_ref (priv->outbox_msg);
1646 data->draft_msg = NULL;
1649 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1651 gtk_text_buffer_get_bounds (buf, &b, &e);
1652 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1654 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1655 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1657 data->html_body = NULL;
1659 /* deep-copy the data */
1660 att_iter = tny_list_create_iterator (priv->attachments);
1661 data->attachments = NULL;
1662 while (!tny_iterator_is_done (att_iter)) {
1663 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1664 if (!(TNY_IS_MIME_PART(part))) {
1665 g_warning ("strange data in attachment list");
1666 g_object_unref (part);
1667 tny_iterator_next (att_iter);
1670 data->attachments = g_list_append (data->attachments,
1672 tny_iterator_next (att_iter);
1674 g_object_unref (att_iter);
1676 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1677 att_iter = tny_list_create_iterator (priv->images);
1678 data->images = NULL;
1679 while (!tny_iterator_is_done (att_iter)) {
1680 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1682 if (!(TNY_IS_MIME_PART(part))) {
1683 g_warning ("strange data in attachment list");
1684 g_object_unref (part);
1685 tny_iterator_next (att_iter);
1688 cid = tny_mime_part_get_content_id (part);
1690 gchar *image_tag_id;
1691 GtkTextTag *image_tag;
1693 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1694 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1695 g_free (image_tag_id);
1697 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1699 ((gtk_text_iter_has_tag (&iter, image_tag))||
1700 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1701 data->images = g_list_append (data->images,
1702 g_object_ref (part));
1704 g_object_unref (part);
1705 tny_iterator_next (att_iter);
1707 g_object_unref (att_iter);
1709 data->priority_flags = priv->priority_flags;
1716 unref_gobject (GObject *obj, gpointer data)
1718 if (!G_IS_OBJECT(obj))
1720 g_object_unref (obj);
1724 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1727 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1735 g_free (data->from);
1736 g_free (data->subject);
1737 g_free (data->plain_body);
1738 g_free (data->html_body);
1739 g_free (data->account_name);
1741 if (data->draft_msg != NULL) {
1742 g_object_unref (data->draft_msg);
1743 data->draft_msg = NULL;
1746 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1747 g_list_free (data->attachments);
1748 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1749 g_list_free (data->images);
1751 g_slice_free (MsgData, data);
1755 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1757 guint64 *parts_size)
1759 ModestMsgEditWindowPrivate *priv;
1761 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1763 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1765 /* TODO: add images */
1766 *parts_size += priv->images_size;
1767 *parts_count += priv->images_count;
1772 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1775 ModestMsgEditWindowPrivate *priv = NULL;
1776 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1778 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1780 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1782 return MODEST_MSG_EDIT_FORMAT_HTML;
1784 return MODEST_MSG_EDIT_FORMAT_TEXT;
1788 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1789 ModestMsgEditFormat format)
1791 ModestMsgEditWindowPrivate *priv;
1793 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1794 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1797 case MODEST_MSG_EDIT_FORMAT_HTML:
1798 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1800 case MODEST_MSG_EDIT_FORMAT_TEXT:
1801 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1804 g_return_if_reached ();
1808 ModestMsgEditFormatState *
1809 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1811 ModestMsgEditFormatState *format_state = NULL;
1812 ModestMsgEditWindowPrivate *priv;
1813 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1815 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1816 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1818 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1820 format_state = g_new0 (ModestMsgEditFormatState, 1);
1821 format_state->bold = buffer_format->bold&0x1;
1822 format_state->italics = buffer_format->italic&0x1;
1823 format_state->bullet = buffer_format->bullet&0x1;
1824 format_state->color = buffer_format->color;
1825 format_state->font_size = buffer_format->font_size;
1826 format_state->font_family = wp_get_font_name (buffer_format->font);
1827 format_state->justification = buffer_format->justification;
1828 g_free (buffer_format);
1830 return format_state;
1835 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1836 const ModestMsgEditFormatState *format_state)
1838 ModestMsgEditWindowPrivate *priv;
1839 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1840 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1841 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1842 g_return_if_fail (format_state != NULL);
1844 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1845 gtk_widget_grab_focus (priv->msg_body);
1846 buffer_format->bold = (format_state->bold != FALSE);
1847 buffer_format->italic = (format_state->italics != FALSE);
1848 buffer_format->color = format_state->color;
1849 buffer_format->font_size = format_state->font_size;
1850 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1851 buffer_format->justification = format_state->justification;
1852 buffer_format->bullet = format_state->bullet;
1854 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1856 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1857 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1858 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1859 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1860 buffer_format->cs.font = (buffer_format->font != current_format->font);
1861 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1862 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1864 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1865 if (buffer_format->cs.bold) {
1866 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1867 GINT_TO_POINTER (buffer_format->bold&0x1));
1869 if (buffer_format->cs.italic) {
1870 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1871 GINT_TO_POINTER (buffer_format->italic&0x1));
1873 if (buffer_format->cs.color) {
1874 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1875 GINT_TO_POINTER (&(buffer_format->color)));
1877 if (buffer_format->cs.font_size) {
1878 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1879 GINT_TO_POINTER (buffer_format->font_size));
1881 if (buffer_format->cs.justification) {
1882 switch (buffer_format->justification) {
1883 case GTK_JUSTIFY_LEFT:
1884 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1885 GINT_TO_POINTER(TRUE));
1887 case GTK_JUSTIFY_CENTER:
1888 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1889 GINT_TO_POINTER(TRUE));
1891 case GTK_JUSTIFY_RIGHT:
1892 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1893 GINT_TO_POINTER(TRUE));
1900 if (buffer_format->cs.font) {
1901 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1902 GINT_TO_POINTER (buffer_format->font));
1904 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1905 if (buffer_format->cs.bullet) {
1906 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1907 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1909 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1911 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1913 g_free (buffer_format);
1914 g_free (current_format);
1916 /* Check dimming rules */
1917 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1918 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1922 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1924 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1926 ModestWindowPrivate *parent_priv;
1927 ModestMsgEditWindowPrivate *priv;
1928 GtkWidget *new_font_menuitem;
1930 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1931 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1933 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1934 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1935 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1936 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1938 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1939 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1940 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1943 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1945 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1946 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1948 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1949 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1951 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1952 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1955 switch (buffer_format->justification)
1957 case GTK_JUSTIFY_LEFT:
1958 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1960 case GTK_JUSTIFY_CENTER:
1961 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1963 case GTK_JUSTIFY_RIGHT:
1964 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1971 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1973 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1974 G_CALLBACK (modest_msg_edit_window_color_button_change),
1976 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1977 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1978 G_CALLBACK (modest_msg_edit_window_color_button_change),
1981 if (priv->current_size_index != buffer_format->font_size) {
1985 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
1986 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
1989 priv->current_size_index = buffer_format->font_size;
1991 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
1992 markup = g_strconcat ("<span font_family='Sans'>",
1993 size_text, "</span>", NULL);
1995 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1999 gtk_tree_path_free (path);
2002 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
2003 buffer_format->font))->data);
2004 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
2008 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2009 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2010 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2012 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2013 G_CALLBACK (modest_msg_edit_window_font_change),
2015 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2016 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2017 G_CALLBACK (modest_msg_edit_window_font_change),
2021 g_free (buffer_format);
2025 #ifdef MODEST_HILDON_VERSION_0
2027 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2030 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2031 ModestMsgEditWindowPrivate *priv;
2032 GtkWidget *dialog = NULL;
2034 GdkColor *new_color = NULL;
2036 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2037 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2039 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2040 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2041 g_free (buffer_format);
2043 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2044 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2045 if (new_color != NULL) {
2046 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2047 (gpointer) new_color);
2050 gtk_widget_destroy (dialog);
2055 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2058 ModestMsgEditWindowPrivate *priv;
2059 GtkWidget *dialog = NULL;
2061 GdkColor *old_color = NULL;
2062 const GdkColor *new_color = NULL;
2064 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2065 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2067 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2068 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2070 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2071 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2072 if (new_color != NULL)
2073 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2075 gtk_widget_destroy (dialog);
2081 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2084 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2085 ModestMsgEditWindowPrivate *priv;
2086 GtkWidget *dialog = NULL;
2088 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2089 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2091 dialog = hildon_color_chooser_new ();
2092 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2093 g_free (buffer_format);
2095 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2097 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2098 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2101 gtk_widget_destroy (dialog);
2106 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2109 ModestMsgEditWindowPrivate *priv;
2110 GtkWidget *dialog = NULL;
2111 GdkColor *old_color = NULL;
2113 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2114 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2116 dialog = hildon_color_chooser_new ();
2117 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2119 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2121 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2122 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2124 gtk_widget_destroy (dialog);
2127 #endif /*!MODEST_HILDON_VERSION_0*/
2132 create_stream_for_uri (const gchar* uri)
2137 TnyStream *result = NULL;
2139 GnomeVFSHandle *handle = NULL;
2140 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2141 if (test == GNOME_VFS_OK) {
2142 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2143 /* Streams over OBEX (Bluetooth) are not seekable but
2144 * we expect them to be (we might need to read them
2145 * several times). So if this is a Bluetooth URI just
2146 * read the whole file into memory (this is not a fast
2147 * protocol so we can assume that these files are not
2148 * going to be very big) */
2149 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2150 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2151 TnyStream *memstream = tny_camel_mem_stream_new ();
2152 tny_stream_write_to_stream (vfssstream, memstream);
2153 g_object_unref (vfssstream);
2156 result = vfssstream;
2164 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2167 ModestMsgEditWindowPrivate *priv;
2168 GtkWidget *dialog = NULL;
2170 GSList *uris = NULL;
2171 GSList *uri_node = NULL;
2173 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2175 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2176 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2177 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2179 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2181 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2182 GTK_WINDOW (dialog), GTK_WINDOW (window));
2184 response = gtk_dialog_run (GTK_DIALOG (dialog));
2186 case GTK_RESPONSE_OK:
2187 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2192 gtk_widget_destroy (dialog);
2194 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2196 GnomeVFSHandle *handle = NULL;
2197 GnomeVFSResult result;
2198 GtkTextIter position;
2199 GtkTextMark *insert_mark;
2201 uri = (const gchar *) uri_node->data;
2202 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2203 if (result == GNOME_VFS_OK) {
2205 GnomeVFSFileInfo *info;
2206 gchar *filename, *basename, *escaped_filename;
2207 TnyMimePart *mime_part;
2209 const gchar *mime_type = NULL;
2210 GnomeVFSURI *vfs_uri;
2211 guint64 stream_size;
2213 gnome_vfs_close (handle);
2214 vfs_uri = gnome_vfs_uri_new (uri);
2216 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2217 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2218 g_free (escaped_filename);
2219 gnome_vfs_uri_unref (vfs_uri);
2220 info = gnome_vfs_file_info_new ();
2222 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2223 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2225 mime_type = gnome_vfs_file_info_get_mime_type (info);
2227 mime_part = tny_platform_factory_new_mime_part
2228 (modest_runtime_get_platform_factory ());
2230 TnyStream *stream = create_stream_for_uri (uri);
2232 if (stream == NULL) {
2234 modest_platform_information_banner (NULL, NULL,
2235 _FM("sfil_ib_opening_not_allowed"));
2237 g_object_unref (mime_part);
2238 gnome_vfs_file_info_unref (info);
2242 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2244 content_id = g_strdup_printf ("%d", priv->next_cid);
2245 tny_mime_part_set_content_id (mime_part, content_id);
2246 g_free (content_id);
2249 basename = g_path_get_basename (filename);
2250 tny_mime_part_set_filename (mime_part, basename);
2253 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2255 if (pixbuf != NULL) {
2256 priv->images_size += stream_size;
2257 priv->images_count ++;
2258 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2259 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2260 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2261 g_object_unref (pixbuf);
2264 tny_list_prepend (priv->images, (GObject *) mime_part);
2265 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2267 g_object_unref (mime_part);
2268 gnome_vfs_file_info_unref (info);
2277 on_attach_file_response (GtkDialog *dialog,
2281 GSList *uris = NULL;
2283 GnomeVFSFileSize total_size, allowed_size;
2284 ModestMsgEditWindow *window;
2285 ModestMsgEditWindowPrivate *priv;
2290 case GTK_RESPONSE_OK:
2291 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2297 window = MODEST_MSG_EDIT_WINDOW (user_data);
2298 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2300 /* allowed size is the maximum size - what's already there */
2301 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2302 &att_num, &att_size);
2303 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2306 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2308 const gchar *uri = (const gchar *) uri_node->data;
2311 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2313 if (total_size > allowed_size) {
2314 g_warning ("%s: total size: %u",
2315 __FUNCTION__, (unsigned int)total_size);
2318 allowed_size -= total_size;
2320 g_slist_foreach (uris, (GFunc) g_free, NULL);
2321 g_slist_free (uris);
2323 gtk_widget_destroy (GTK_WIDGET (dialog));
2327 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2329 GtkWidget *dialog = NULL;
2330 ModestMsgEditWindowPrivate *priv;
2332 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2334 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2336 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2339 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2340 GTK_FILE_CHOOSER_ACTION_OPEN);
2341 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2342 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2343 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2344 GTK_WINDOW (dialog), GTK_WINDOW (window));
2346 /* Connect to response & show */
2347 g_signal_connect (dialog, "response",
2348 G_CALLBACK (on_attach_file_response), window);
2349 gtk_widget_show (dialog);
2354 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2356 GnomeVFSFileSize allowed_size)
2359 GnomeVFSHandle *handle = NULL;
2360 ModestMsgEditWindowPrivate *priv;
2361 GnomeVFSResult result;
2362 GnomeVFSFileSize size = 0;
2363 g_return_val_if_fail (window, 0);
2364 g_return_val_if_fail (uri, 0);
2366 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2368 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2369 if (result == GNOME_VFS_OK) {
2370 TnyMimePart *mime_part;
2372 const gchar *mime_type = NULL;
2374 gchar *escaped_filename;
2377 GnomeVFSFileInfo *info;
2378 GnomeVFSURI *vfs_uri;
2380 gnome_vfs_close (handle);
2381 vfs_uri = gnome_vfs_uri_new (uri);
2384 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2385 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2386 g_free (escaped_filename);
2387 gnome_vfs_uri_unref (vfs_uri);
2389 info = gnome_vfs_file_info_new ();
2391 if (gnome_vfs_get_file_info (uri,
2393 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2395 mime_type = gnome_vfs_file_info_get_mime_type (info);
2396 mime_part = tny_platform_factory_new_mime_part
2397 (modest_runtime_get_platform_factory ());
2399 /* try to get the attachment's size; this may fail for weird
2400 * file systems, like obex, upnp... */
2401 if (allowed_size != 0 &&
2402 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2404 if (size > allowed_size) {
2405 modest_platform_information_banner (NULL, NULL,
2406 _FM("sfil_ib_opening_not_allowed"));
2410 g_warning ("%s: could not get attachment size", __FUNCTION__);
2412 stream = create_stream_for_uri (uri);
2414 if (stream == NULL) {
2416 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2418 g_object_unref (mime_part);
2419 gnome_vfs_file_info_unref (info);
2423 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2424 g_object_unref (stream);
2426 content_id = g_strdup_printf ("%d", priv->next_cid);
2427 tny_mime_part_set_content_id (mime_part, content_id);
2428 g_free (content_id);
2431 basename = g_path_get_basename (filename);
2432 tny_mime_part_set_filename (mime_part, basename);
2435 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2436 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2438 info->size == 0, info->size);
2439 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2440 gtk_widget_show_all (priv->attachments_caption);
2441 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2443 g_object_unref (mime_part);
2444 gnome_vfs_file_info_unref (info);
2451 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2454 ModestMsgEditWindowPrivate *priv;
2457 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2458 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2460 if (att_list == NULL) {
2461 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2462 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2463 g_object_unref (att_list);
2468 g_object_ref (att_list);
2471 if (tny_list_get_length (att_list) == 0) {
2472 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2474 gboolean dialog_response;
2475 gchar *message = NULL;
2476 gchar *filename = NULL;
2478 if (tny_list_get_length (att_list) == 1) {
2480 iter = tny_list_create_iterator (att_list);
2481 part = (TnyMimePart *) tny_iterator_get_current (iter);
2482 g_object_unref (iter);
2483 if (TNY_IS_MSG (part)) {
2484 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2486 filename = tny_header_dup_subject (header);
2487 g_object_unref (header);
2489 if (filename == NULL) {
2490 filename = g_strdup (_("mail_va_no_subject"));
2493 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2495 g_object_unref (part);
2497 filename = g_strdup ("");
2499 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2500 "emev_nc_delete_attachments",
2501 tny_list_get_length (att_list)), filename);
2504 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2508 if (dialog_response != GTK_RESPONSE_OK) {
2509 g_object_unref (att_list);
2513 for (iter = tny_list_create_iterator (att_list);
2514 !tny_iterator_is_done (iter);
2515 tny_iterator_next (iter)) {
2516 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2517 const gchar *att_id;
2518 tny_list_remove (priv->attachments, (GObject *) mime_part);
2520 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2522 if (tny_list_get_length (priv->attachments) == 0)
2523 gtk_widget_hide (priv->attachments_caption);
2524 att_id = tny_mime_part_get_content_id (mime_part);
2526 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2528 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2529 g_object_unref (mime_part);
2531 g_object_unref (iter);
2534 g_object_unref (att_list);
2536 /* if the last attachment has been removed, focus the Subject: field */
2537 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2538 gtk_widget_grab_focus (priv->subject_field);
2542 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2545 ModestMsgEditWindowPrivate *priv;
2546 GdkColor *new_color;
2547 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2549 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2550 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2553 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2555 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2557 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2559 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2564 font_size_clicked (GtkToolButton *button,
2565 ModestMsgEditWindow *window)
2567 ModestMsgEditWindowPrivate *priv;
2568 GtkWidget *selector, *dialog;
2570 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2572 selector = hildon_touch_selector_new ();
2573 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2574 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2576 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2577 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2579 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2583 WPTextBufferFormat format;
2585 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2587 memset (&format, 0, sizeof (format));
2588 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2590 format.cs.font_size = TRUE;
2591 format.cs.text_position = TRUE;
2592 format.cs.font = TRUE;
2593 format.font_size = new_index;
2594 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2596 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2597 GINT_TO_POINTER (new_index)))
2598 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2600 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2601 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2602 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2603 size_text, "</span>", NULL);
2605 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2609 gtk_widget_destroy (dialog);
2611 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2616 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2619 ModestMsgEditWindowPrivate *priv;
2620 gint new_font_index;
2621 ModestMsgEditWindow *window;
2624 window = MODEST_MSG_EDIT_WINDOW (userdata);
2625 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2626 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2628 if (gtk_check_menu_item_get_active (menu_item)) {
2631 label = gtk_bin_get_child (GTK_BIN (menu_item));
2633 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2635 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2636 GINT_TO_POINTER(new_font_index)))
2637 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2639 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2640 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2641 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2647 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2650 ModestMsgEditWindowPrivate *priv = NULL;
2651 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2653 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2654 if (!priv->update_caption_visibility)
2657 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2659 gtk_widget_show (priv->cc_caption);
2661 gtk_widget_hide (priv->cc_caption);
2663 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2667 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2670 ModestMsgEditWindowPrivate *priv = NULL;
2671 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2673 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2674 if (!priv->update_caption_visibility)
2677 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2679 gtk_widget_show (priv->bcc_caption);
2681 gtk_widget_hide (priv->bcc_caption);
2683 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2687 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2688 ModestRecptEditor *editor)
2690 ModestMsgEditWindowPrivate *priv;
2692 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2693 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2695 /* we check for low-mem; in that case, show a warning, and don't allow
2696 * for the addressbook
2698 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2701 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2703 if (editor == NULL) {
2704 GtkWidget *view_focus;
2705 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2707 /* This code should be kept in sync with ModestRecptEditor. The
2708 textview inside the recpt editor is the one that really gets the
2709 focus. As it's inside a scrolled window, and this one inside the
2710 hbox recpt editor inherits from, we'll need to go up in the
2711 hierarchy to know if the text view is part of the recpt editor
2712 or if it's a different text entry */
2714 if (gtk_widget_get_parent (view_focus)) {
2715 GtkWidget *first_parent;
2717 first_parent = gtk_widget_get_parent (view_focus);
2718 if (gtk_widget_get_parent (first_parent) &&
2719 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2720 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2725 editor = MODEST_RECPT_EDITOR (priv->to_field);
2729 modest_address_book_select_addresses (editor);
2734 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2736 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2738 modest_msg_edit_window_open_addressbook (window, NULL);
2742 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2743 gboolean show_toolbar)
2745 ModestWindowPrivate *parent_priv;
2747 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2748 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2750 /* We can not just use the code of
2751 modest_msg_edit_window_setup_toolbar because it has a
2752 mixture of both initialization and creation code. */
2754 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2756 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2760 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2761 TnyHeaderFlags priority_flags)
2763 ModestMsgEditWindowPrivate *priv;
2764 ModestWindowPrivate *parent_priv;
2766 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2768 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2769 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2771 if (priv->priority_flags != priority_flags) {
2772 GtkAction *priority_action = NULL;
2774 priv->priority_flags = priority_flags;
2776 switch (priority_flags) {
2777 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2778 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2779 MODEST_HEADER_ICON_HIGH,
2780 HILDON_ICON_SIZE_SMALL);
2781 gtk_widget_show (priv->priority_icon);
2782 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2783 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2785 case TNY_HEADER_FLAG_LOW_PRIORITY:
2786 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2787 MODEST_HEADER_ICON_LOW,
2788 HILDON_ICON_SIZE_SMALL);
2789 gtk_widget_show (priv->priority_icon);
2790 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2791 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2794 gtk_widget_hide (priv->priority_icon);
2795 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2796 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2799 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2800 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2802 gtk_widget_queue_resize (priv->subject_box);
2806 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2809 ModestMsgEditWindowPrivate *priv;
2810 ModestWindowPrivate *parent_priv;
2811 gint current_format;
2813 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2815 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2816 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2818 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2819 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2821 if (current_format != file_format) {
2822 switch (file_format) {
2823 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2824 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2825 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2827 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2831 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2832 response = gtk_dialog_run (GTK_DIALOG (dialog));
2833 gtk_widget_destroy (dialog);
2834 if (response == GTK_RESPONSE_OK) {
2835 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2837 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2838 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2843 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2844 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2845 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2850 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2853 ModestMsgEditWindowPrivate *priv;
2854 WPTextBufferFormat oldfmt, fmt;
2855 gint old_position = 0;
2859 GdkColor *color = NULL;
2860 gboolean bold, bold_set, italic, italic_set;
2861 gboolean underline, underline_set;
2862 gboolean strikethrough, strikethrough_set;
2863 gboolean position_set;
2864 gboolean font_size_set, font_set, color_set;
2867 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2868 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2870 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2871 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2872 GTK_WINDOW(dialog), GTK_WINDOW (window));
2874 /* First we get the currently selected font information */
2875 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2877 switch (oldfmt.text_position) {
2878 case TEXT_POSITION_NORMAL:
2881 case TEXT_POSITION_SUPERSCRIPT:
2889 g_object_set (G_OBJECT (dialog),
2890 "bold", oldfmt.bold != FALSE,
2891 "bold-set", !oldfmt.cs.bold,
2892 "underline", oldfmt.underline != FALSE,
2893 "underline-set", !oldfmt.cs.underline,
2894 "italic", oldfmt.italic != FALSE,
2895 "italic-set", !oldfmt.cs.italic,
2896 "strikethrough", oldfmt.strikethrough != FALSE,
2897 "strikethrough-set", !oldfmt.cs.strikethrough,
2898 "color", &oldfmt.color,
2899 "color-set", !oldfmt.cs.color,
2900 "size", wp_font_size[oldfmt.font_size],
2901 "size-set", !oldfmt.cs.font_size,
2902 "position", old_position,
2903 "position-set", !oldfmt.cs.text_position,
2904 "family", wp_get_font_name (oldfmt.font),
2905 "family-set", !oldfmt.cs.font,
2908 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2909 GTK_WINDOW (dialog), GTK_WINDOW (window));
2910 gtk_widget_show_all (dialog);
2911 priv->font_dialog = dialog;
2912 response = gtk_dialog_run (GTK_DIALOG (dialog));
2913 priv->font_dialog = NULL;
2914 if (response == GTK_RESPONSE_OK) {
2916 g_object_get( dialog,
2918 "bold-set", &bold_set,
2919 "underline", &underline,
2920 "underline-set", &underline_set,
2922 "italic-set", &italic_set,
2923 "strikethrough", &strikethrough,
2924 "strikethrough-set", &strikethrough_set,
2926 "color-set", &color_set,
2928 "size-set", &font_size_set,
2929 "family", &font_name,
2930 "family-set", &font_set,
2931 "position", &position,
2932 "position-set", &position_set,
2937 if (response == GTK_RESPONSE_OK) {
2938 memset(&fmt, 0, sizeof(fmt));
2944 fmt.italic = italic;
2945 fmt.cs.italic = TRUE;
2947 if (underline_set) {
2948 fmt.underline = underline;
2949 fmt.cs.underline = TRUE;
2951 if (strikethrough_set) {
2952 fmt.strikethrough = strikethrough;
2953 fmt.cs.strikethrough = TRUE;
2958 ? TEXT_POSITION_NORMAL
2959 : ( ( position == 1 )
2960 ? TEXT_POSITION_SUPERSCRIPT
2961 : TEXT_POSITION_SUBSCRIPT );
2962 fmt.cs.text_position = TRUE;
2963 fmt.font_size = oldfmt.font_size;
2967 fmt.cs.color = TRUE;
2970 fmt.font = wp_get_font_index(font_name,
2975 if (font_size_set) {
2976 fmt.cs.font_size = TRUE;
2977 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2979 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2980 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2982 gtk_widget_destroy (dialog);
2984 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2988 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2990 ModestMsgEditWindowPrivate *priv;
2992 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2993 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2995 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2997 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2998 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3002 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3004 ModestMsgEditWindowPrivate *priv;
3006 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3007 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3009 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3011 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3012 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3017 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3019 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3021 priv->can_undo = can_undo;
3025 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3027 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3029 priv->can_redo = can_redo;
3033 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3035 ModestMsgEditWindowPrivate *priv;
3036 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3037 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3039 return priv->can_undo;
3043 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3045 ModestMsgEditWindowPrivate *priv;
3046 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3047 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3049 return priv->can_redo;
3054 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3057 GtkTextIter match_start, match_end;
3059 if (image_id == NULL)
3062 gtk_text_buffer_get_start_iter (buffer, &iter);
3064 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3065 GSList *tags = gtk_text_iter_get_tags (&match_start);
3067 for (node = tags; node != NULL; node = g_slist_next (node)) {
3068 GtkTextTag *tag = (GtkTextTag *) node->data;
3069 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3070 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3071 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3073 offset = gtk_text_iter_get_offset (&match_start);
3074 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3075 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3079 gtk_text_iter_forward_char (&iter);
3084 message_is_empty (ModestMsgEditWindow *window)
3086 ModestMsgEditWindowPrivate *priv = NULL;
3088 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3089 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3091 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3092 * so we can ignore markup.
3094 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3097 count = gtk_text_buffer_get_char_count (buf);
3103 msg_body_focus (GtkWidget *focus,
3104 GdkEventFocus *event,
3108 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3109 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3110 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3115 recpt_field_changed (GtkTextBuffer *buffer,
3116 ModestMsgEditWindow *editor)
3118 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3119 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3123 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3125 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3126 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3130 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3133 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3134 GtkTextBuffer *buffer;
3136 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3137 gtk_text_buffer_set_modified (buffer, modified);
3138 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3139 gtk_text_buffer_set_modified (buffer, modified);
3140 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3141 gtk_text_buffer_set_modified (buffer, modified);
3142 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3146 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3148 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3149 const char *account_name;
3150 GtkTextBuffer *buffer;
3152 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3153 if (gtk_text_buffer_get_modified (buffer))
3155 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3156 if (gtk_text_buffer_get_modified (buffer))
3158 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3159 if (gtk_text_buffer_get_modified (buffer))
3161 if (gtk_text_buffer_get_modified (priv->text_buffer))
3163 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3164 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3175 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3177 ModestMsgEditWindowPrivate *priv = NULL;
3179 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3180 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3182 /* check if there's no recipient added */
3183 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3184 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3185 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3186 /* no recipient contents, then select contacts */
3187 modest_msg_edit_window_open_addressbook (window, NULL);
3191 g_object_ref (window);
3192 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3193 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3194 g_object_unref (window);
3197 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3198 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3199 g_object_unref (window);
3202 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3203 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3204 g_object_unref (window);
3208 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3209 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3210 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3211 g_object_unref (window);
3218 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3219 ModestMsgEditWindow *window)
3221 modest_msg_edit_window_offer_attach_file (window);
3225 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3227 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3229 return priv->clipboard_text;
3233 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3235 ModestMsgEditWindow *window)
3237 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3238 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3240 if (!GTK_WIDGET_VISIBLE (window))
3243 g_object_ref (window);
3244 text = gtk_clipboard_wait_for_text (selection_clipboard);
3246 if (priv->clipboard_text != NULL) {
3247 g_free (priv->clipboard_text);
3249 priv->clipboard_text = text;
3251 if (GTK_WIDGET_VISIBLE (window)) {
3252 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3254 g_object_unref (window);
3257 static gboolean clipboard_owner_change_idle (gpointer userdata)
3259 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3260 ModestMsgEditWindowPrivate *priv;
3262 gdk_threads_enter ();
3263 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3264 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3266 priv->clipboard_owner_idle = 0;
3267 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3268 gdk_threads_leave ();
3274 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3276 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3277 if (priv->clipboard_owner_idle == 0) {
3278 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3283 subject_field_move_cursor (GtkEntry *entry,
3284 GtkMovementStep step,
3289 if (!GTK_WIDGET_VISIBLE (window))
3292 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3296 update_window_title (ModestMsgEditWindow *window)
3298 ModestMsgEditWindowPrivate *priv = NULL;
3299 const gchar *subject;
3301 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3302 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3303 if (subject == NULL || subject[0] == '\0')
3304 subject = _("mail_va_new_email");
3306 gtk_window_set_title (GTK_WINDOW (window), subject);
3311 subject_field_changed (GtkEditable *editable,
3312 ModestMsgEditWindow *window)
3314 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3315 update_window_title (window);
3316 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3317 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3318 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3322 subject_field_insert_text (GtkEditable *editable,
3324 gint new_text_length,
3326 ModestMsgEditWindow *window)
3328 GString *result = g_string_new ("");
3330 gint result_len = 0;
3331 const gchar *entry_text = NULL;
3334 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3335 old_length = g_utf8_strlen (entry_text, -1);
3337 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3338 gunichar c = g_utf8_get_char_validated (current, 8);
3339 /* Invalid unichar, stop */
3345 result = g_string_append_unichar (result, c);
3349 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3350 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3353 /* Prevent endless recursion */
3354 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3355 g_signal_emit_by_name (editable, "insert-text",
3356 (gpointer) result->str, (gpointer) result->len,
3357 (gpointer) position, (gpointer) window);
3358 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3362 if (result_len + old_length > 1000) {
3363 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3364 _CS("ckdg_ib_maximum_characters_reached"));
3366 g_string_free (result, TRUE);
3370 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3373 ModestMsgEditWindowPrivate *priv = NULL;
3375 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3376 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3378 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3381 gtk_widget_show_all (priv->find_toolbar);
3382 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3384 gtk_widget_hide_all (priv->find_toolbar);
3385 gtk_widget_grab_focus (priv->msg_body);
3390 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3392 GtkTextIter *match_start,
3393 GtkTextIter *match_end)
3395 GtkTextIter end_iter;
3396 gchar *str_casefold;
3399 gchar *range_casefold;
3402 gboolean result = FALSE;
3409 gtk_text_iter_forward_to_end (&end_iter);
3411 str_casefold = g_utf8_casefold (str, -1);
3412 str_chars_n = strlen (str);
3414 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3415 range_casefold = g_utf8_casefold (range_text, -1);
3416 range_chars_n = strlen (range_casefold);
3418 if (range_chars_n < str_chars_n) {
3419 g_free (str_casefold);
3420 g_free (range_text);
3421 g_free (range_casefold);
3425 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3426 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3427 if (!g_utf8_collate (range_subtext, str_casefold)) {
3428 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3430 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3431 match_start, match_end, NULL);
3432 g_free (found_text);
3434 g_free (range_subtext);
3438 g_free (str_casefold);
3439 g_free (range_text);
3440 g_free (range_casefold);
3447 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3448 ModestMsgEditWindow *window)
3450 gchar *current_search = NULL;
3451 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3453 GtkTextIter selection_start, selection_end;
3454 GtkTextIter match_start, match_end;
3455 gboolean continue_search = FALSE;
3457 if (message_is_empty (window)) {
3458 g_free (priv->last_search);
3459 priv->last_search = NULL;
3460 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3464 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3465 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3466 g_free (current_search);
3467 g_free (priv->last_search);
3468 priv->last_search = NULL;
3469 /* Information banner about empty search */
3470 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3474 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3475 continue_search = TRUE;
3477 g_free (priv->last_search);
3478 priv->last_search = g_strdup (current_search);
3481 if (continue_search) {
3482 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3483 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3484 &match_start, &match_end);
3486 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3488 GtkTextIter buffer_start;
3489 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3490 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3491 &match_start, &match_end);
3493 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3496 /* Mark as selected the string found in search */
3498 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3499 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3500 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3502 g_free (priv->last_search);
3503 priv->last_search = NULL;
3505 g_free (current_search);
3509 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3511 ModestMsgEditWindowPrivate *priv;
3513 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3518 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3521 ModestMsgEditWindowPrivate *priv;
3523 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3528 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3529 ModestMsgEditWindow *window)
3531 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3535 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3538 ModestMsgEditWindowPrivate *priv;
3539 TnyHeader *header = NULL;
3541 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3542 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3544 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3545 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3547 if (priv->draft_msg != NULL) {
3548 g_object_unref (priv->draft_msg);
3551 if (draft != NULL) {
3552 g_object_ref (draft);
3553 header = tny_msg_get_header (draft);
3554 if (priv->msg_uid) {
3555 g_free (priv->msg_uid);
3556 priv->msg_uid = NULL;
3558 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3559 if (GTK_WIDGET_REALIZED (window)) {
3560 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3561 gtk_widget_destroy (GTK_WIDGET (window));
3567 priv->draft_msg = draft;
3571 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3572 GtkTextIter *start, GtkTextIter *end,
3575 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3576 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3579 if (tag == NULL) return;
3580 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3581 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3582 replace_with_images (window, priv->images);
3587 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3590 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3592 g_return_if_fail (TNY_IS_MIME_PART (part));
3593 tny_list_prepend (priv->attachments, (GObject *) part);
3594 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3595 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3596 gtk_widget_show_all (priv->attachments_caption);
3597 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3601 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3603 ModestMsgEditWindowPrivate *priv;
3605 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3606 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3608 return priv->msg_uid;
3612 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3613 ModestMsgEditWindowWidgetType widget_type)
3615 ModestMsgEditWindowPrivate *priv;
3617 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3618 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3620 switch (widget_type) {
3621 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3622 return priv->msg_body;
3624 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3625 return priv->to_field;
3627 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3628 return priv->cc_field;
3630 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3631 return priv->bcc_field;
3633 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3634 return priv->subject_field;
3636 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3637 return priv->attachments_view;
3645 remove_tags (WPTextBuffer *buffer)
3647 GtkTextIter start, end;
3649 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3650 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3652 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3656 on_account_removed (TnyAccountStore *account_store,
3657 TnyAccount *account,
3660 /* Do nothing if it's a store account, because we use the
3661 transport to send the messages */
3662 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3663 const gchar *parent_acc = NULL;
3664 const gchar *our_acc = NULL;
3666 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3667 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3668 /* Close this window if I'm showing a message of the removed account */
3669 if (strcmp (parent_acc, our_acc) == 0)
3670 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3675 from_field_changed (HildonPickerButton *button,
3676 ModestMsgEditWindow *self)
3678 ModestMsgEditWindowPrivate *priv;
3679 gboolean has_old_signature, has_new_signature;
3681 GtkTextIter match_start, match_end;
3682 ModestAccountMgr *mgr;
3684 gchar *full_signature;
3686 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3688 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3689 mgr = modest_runtime_get_account_mgr ();
3690 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_old_signature);
3691 if (has_old_signature) {
3692 full_signature = g_strconcat ("\n--\n", signature, NULL);
3693 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3694 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3696 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3697 &match_start, &match_end, NULL)) {
3700 g_free (full_signature);
3704 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3705 signature = modest_account_mgr_get_signature (mgr, priv->last_from_account, &has_new_signature);
3706 if (has_new_signature) {
3707 full_signature = g_strconcat ("\n--\n", signature, NULL);
3708 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3709 g_free (full_signature);
3714 typedef struct _MessageSettingsHelper {
3715 ModestMsgEditWindow *window;
3716 GSList *priority_group;
3717 GSList *format_group;
3718 GtkToggleButton *current_priority;
3719 GtkToggleButton *current_format;
3720 } MessageSettingsHelper;
3723 on_priority_toggle (GtkToggleButton *button,
3724 MessageSettingsHelper *helper)
3727 ModestMsgEditWindowPrivate *priv;
3729 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3730 if (gtk_toggle_button_get_active (button)) {
3732 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3733 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3734 if ((node_button != button) &&
3735 gtk_toggle_button_get_active (node_button)) {
3736 gtk_toggle_button_set_active (node_button, FALSE);
3739 helper->current_priority = button;
3741 gboolean found = FALSE;
3742 /* If no one is active, activate it again */
3743 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3744 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3745 if (gtk_toggle_button_get_active (node_button)) {
3751 gtk_toggle_button_set_active (button, TRUE);
3757 on_format_toggle (GtkToggleButton *button,
3758 MessageSettingsHelper *helper)
3761 ModestMsgEditWindowPrivate *priv;
3763 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3764 if (gtk_toggle_button_get_active (button)) {
3766 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3767 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3768 if ((node_button != button) &&
3769 gtk_toggle_button_get_active (node_button)) {
3770 gtk_toggle_button_set_active (node_button, FALSE);
3773 helper->current_format = button;
3775 gboolean found = FALSE;
3776 /* If no one is active, activate it again */
3777 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
3778 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3779 if (gtk_toggle_button_get_active (node_button)) {
3785 gtk_toggle_button_set_active (button, TRUE);
3792 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3797 GtkWidget *priority_hbox;
3798 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3799 GtkWidget *captioned;
3800 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3801 GtkWidget *format_hbox;
3802 GtkWidget *html_toggle, *text_toggle;
3803 ModestMsgEditWindowPrivate *priv;
3804 MessageSettingsHelper helper = {0,};
3806 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3807 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3808 helper.window = window;
3809 helper.priority_group = NULL;
3810 helper.format_group = NULL;
3812 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3813 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3815 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
3816 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3817 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
3818 vbox = gtk_vbox_new (FALSE, 0);
3819 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
3820 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
3821 gtk_container_add (GTK_CONTAINER (align), vbox);
3822 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
3823 gtk_widget_show (align);
3824 gtk_widget_show (vbox);
3826 /* Priority toggles */
3827 priority_hbox = gtk_hbox_new (TRUE, 0);
3828 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3829 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3830 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3831 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3832 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3833 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3834 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3835 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3836 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3837 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3838 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3839 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3840 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
3841 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
3842 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
3843 gtk_widget_show_all (priority_hbox);
3844 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3845 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
3846 gtk_widget_show (captioned);
3847 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3849 /* format toggles */
3850 format_hbox = gtk_hbox_new (TRUE, 0);
3851 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3852 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
3853 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
3854 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
3855 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
3856 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
3857 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
3858 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
3859 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
3860 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
3861 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
3862 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
3863 gtk_widget_show_all (format_hbox);
3864 gtk_widget_show (format_hbox);
3865 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
3868 g_object_unref (title_sizegroup);
3869 g_object_unref (value_sizegroup);
3871 /* Set current values */
3872 switch (priv->priority_flags) {
3873 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3874 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
3875 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
3877 case TNY_HEADER_FLAG_LOW_PRIORITY:
3878 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
3879 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
3882 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
3883 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
3887 switch (modest_msg_edit_window_get_format (window)) {
3888 case MODEST_MSG_EDIT_FORMAT_TEXT:
3889 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
3890 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
3892 case MODEST_MSG_EDIT_FORMAT_HTML:
3894 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
3895 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
3899 /* Signal connects */
3900 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3901 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3902 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3903 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3904 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
3906 /* Save settings if the user clicked on done */
3907 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
3908 TnyHeaderFlags flags;
3909 ModestMsgEditFormat old_format, new_format;
3911 /* Set priority flags */
3912 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
3913 if (priv->priority_flags != flags)
3914 modest_msg_edit_window_set_priority_flags (window, flags);
3916 /* Set edit format */
3917 old_format = modest_msg_edit_window_get_format (window);
3918 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
3919 if (old_format != new_format) {
3920 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
3921 modest_msg_edit_window_set_file_format (window, file_format);
3925 gtk_widget_destroy (dialog);
3926 g_slist_free (helper.priority_group);
3930 on_message_settings (GtkAction *action,
3931 ModestMsgEditWindow *window)
3933 modest_msg_edit_window_show_msg_settings_dialog (window);
3937 on_cc_button_toggled (HildonCheckButton *button,
3938 ModestMsgEditWindow *window)
3940 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3942 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
3943 hildon_check_button_get_active (button));
3947 on_bcc_button_toggled (HildonCheckButton *button,
3948 ModestMsgEditWindow *window)
3950 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
3952 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
3953 hildon_check_button_get_active (button));
3957 setup_menu (ModestMsgEditWindow *self)
3959 ModestMsgEditWindowPrivate *priv = NULL;
3961 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3963 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3965 /* Settings menu buttons */
3966 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
3967 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
3969 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
3970 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
3971 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
3973 priv->cc_button = hildon_check_button_new (0);
3974 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
3975 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3977 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
3979 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
3980 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
3981 priv->bcc_button = hildon_check_button_new (0);
3982 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
3983 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3985 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
3987 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
3988 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
3990 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
3991 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
3992 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
3993 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
3994 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
3995 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
3996 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
3997 APP_MENU_CALLBACK (on_message_settings),
3999 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4000 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),