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 <wptextview.h>
65 #include <wptextbuffer.h>
66 #include <hildon/hildon-pannable-area.h>
67 #include "modest-msg-edit-window-ui-dimming.h"
69 #include "modest-hildon-includes.h"
70 #ifdef MODEST_HAVE_HILDON0_WIDGETS
71 #include <hildon-widgets/hildon-color-chooser.h>
73 #include "widgets/modest-msg-edit-window-ui.h"
74 #ifdef MODEST_HAVE_HILDON0_WIDGETS
75 #include <libgnomevfs/gnome-vfs-mime-utils.h>
77 #include <libgnomevfs/gnome-vfs-mime.h>
79 #include <modest-utils.h>
80 #include "modest-maemo-utils.h"
81 #include <modest-ui-constants.h>
84 #define DEFAULT_FONT_SIZE 3
85 #define DEFAULT_FONT 2
86 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
87 #define DEFAULT_MAIN_VBOX_SPACING 6
88 #define SUBJECT_MAX_LENGTH 1000
89 #define IMAGE_MAX_WIDTH 560
90 #define DEFAULT_FONT_SCALE 1.5
92 static gboolean is_wp_text_buffer_started = FALSE;
94 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
95 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
96 static void modest_msg_edit_window_finalize (GObject *obj);
98 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
99 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
100 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
102 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
103 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
104 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
105 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
106 GtkTextIter *start, GtkTextIter *end,
108 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
109 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
110 static void subject_field_insert_text (GtkEditable *editable,
112 gint new_text_length,
114 ModestMsgEditWindow *window);
115 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
117 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
119 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
121 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
123 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
124 ModestRecptEditor *editor);
125 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
126 ModestMsgEditWindow *window);
128 /* ModestWindow methods implementation */
129 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
130 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
131 gboolean show_toolbar);
132 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
134 ModestMsgEditWindow *window);
135 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
136 static void subject_field_move_cursor (GtkEntry *entry,
137 GtkMovementStep step,
141 static void update_window_title (ModestMsgEditWindow *window);
144 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
145 ModestMsgEditWindow *window);
146 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
147 ModestMsgEditWindow *window);
148 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
150 GtkTextIter *match_start,
151 GtkTextIter *match_end);
153 static void remove_tags (WPTextBuffer *buffer);
155 static void on_account_removed (TnyAccountStore *account_store,
159 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
160 static void set_zoom_do_nothing (ModestWindow *window, gdouble zoom);
161 static gdouble get_zoom_do_nothing (ModestWindow *window);
163 static void init_window (ModestMsgEditWindow *obj);
165 gboolean scroll_drag_timeout (gpointer userdata);
166 static void correct_scroll (ModestMsgEditWindow *w);
167 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
168 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
169 ModestMsgEditWindow *userdata);
170 static void text_buffer_mark_set (GtkTextBuffer *buffer,
173 ModestMsgEditWindow *userdata);
174 static void on_message_settings (GtkAction *action,
175 ModestMsgEditWindow *window);
176 static void add_to_menu (ModestMsgEditWindow *self,
180 ModestDimmingRulesGroup *group,
181 GCallback dimming_callback);
182 static void setup_menu (ModestMsgEditWindow *self,
183 ModestDimmingRulesGroup *group);
184 static gboolean modest_msg_edit_window_toggle_menu (HildonWindow *window,
188 static void DEBUG_BUFFER (WPTextBuffer *buffer)
192 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
194 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
195 while (!gtk_text_iter_is_end (&iter)) {
196 GString *output = g_string_new ("");
197 GSList *toggled_tags;
200 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
201 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
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, "] OPENED [ ");
210 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
211 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
212 GtkTextTag *tag = (GtkTextTag *) node->data;
214 g_object_get (G_OBJECT (tag), "name", &name, NULL);
215 output = g_string_append (output, name);
216 g_string_append (output, " ");
218 output = g_string_append (output, "]\n");
219 g_message ("%s", output->str);
220 g_string_free (output, TRUE);
221 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
223 g_message ("END BUFFER");
227 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
228 { "MessageSettings", NULL, N_("TODO: settings..."), NULL, NULL, G_CALLBACK (on_message_settings)},
232 /* static gboolean */
233 /* on_key_pressed (GtkWidget *self, */
234 /* GdkEventKey *event, */
235 /* gpointer user_data); */
237 /* list my signals */
244 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
245 struct _ModestMsgEditWindowPrivate {
248 GtkWidget *header_box;
250 ModestPairList *from_field_protos;
251 GtkWidget *from_field;
252 gchar *original_account_name;
256 GtkWidget *bcc_field;
257 GtkWidget *subject_field;
258 GtkWidget *attachments_view;
259 GtkWidget *priority_icon;
260 GtkWidget *add_attachment_button;
262 GtkWidget *cc_caption;
263 GtkWidget *bcc_caption;
264 gboolean update_caption_visibility;
265 GtkWidget *attachments_caption;
267 GtkTextBuffer *text_buffer;
269 GtkWidget *font_size_toolitem;
270 GtkWidget *font_face_toolitem;
271 GtkWidget *font_color_button;
272 GtkWidget *font_color_toolitem;
273 GSList *font_items_group;
274 GtkWidget *font_tool_button_label;
275 GSList *size_items_group;
276 GtkWidget *size_tool_button_label;
278 GtkWidget *find_toolbar;
281 GtkWidget *font_dialog;
284 guint scroll_drag_timeout_id;
288 TnyList *attachments;
293 TnyHeaderFlags priority_flags;
295 gboolean can_undo, can_redo;
296 gulong clipboard_change_handler_id;
297 gulong default_clipboard_change_handler_id;
298 gulong account_removed_handler_id;
299 guint clipboard_owner_idle;
300 gchar *clipboard_text;
311 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
312 MODEST_TYPE_MSG_EDIT_WINDOW, \
313 ModestMsgEditWindowPrivate))
315 static GtkWindowClass *parent_class = NULL;
317 /* uncomment the following if you have defined any signals */
318 /* static guint signals[LAST_SIGNAL] = {0}; */
321 modest_msg_edit_window_get_type (void)
323 static GType my_type = 0;
325 static const GTypeInfo my_info = {
326 sizeof(ModestMsgEditWindowClass),
327 NULL, /* base init */
328 NULL, /* base finalize */
329 (GClassInitFunc) modest_msg_edit_window_class_init,
330 NULL, /* class finalize */
331 NULL, /* class data */
332 sizeof(ModestMsgEditWindow),
334 (GInstanceInitFunc) modest_msg_edit_window_init,
337 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
338 "ModestMsgEditWindow",
346 save_state (ModestWindow *self)
348 modest_widget_memory_save (modest_runtime_get_conf(),
349 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
354 restore_settings (ModestMsgEditWindow *self)
356 ModestConf *conf = NULL;
358 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
360 conf = modest_runtime_get_conf ();
362 /* Dim at start clipboard actions */
363 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
364 gtk_action_set_sensitive (action, FALSE);
365 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
366 gtk_action_set_sensitive (action, FALSE);
367 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
368 gtk_action_set_sensitive (action, FALSE);
370 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
375 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
377 GObjectClass *gobject_class;
378 ModestWindowClass *modest_window_class;
379 HildonWindowClass *hildon_window_class = (HildonWindowClass *) klass;
380 gobject_class = (GObjectClass*) klass;
381 modest_window_class = (ModestWindowClass*) klass;
383 parent_class = g_type_class_peek_parent (klass);
384 gobject_class->finalize = modest_msg_edit_window_finalize;
386 hildon_window_class->toggle_menu = modest_msg_edit_window_toggle_menu;
388 modest_window_class->set_zoom_func = set_zoom_do_nothing;
389 modest_window_class->get_zoom_func = get_zoom_do_nothing;
390 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
391 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
392 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
393 modest_window_class->save_state_func = save_state;
394 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
396 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
400 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
402 ModestMsgEditWindowPrivate *priv;
403 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
405 priv->msg_body = NULL;
407 priv->from_field = NULL;
408 priv->to_field = NULL;
409 priv->cc_field = NULL;
410 priv->bcc_field = NULL;
411 priv->subject_field = NULL;
412 priv->attachments = TNY_LIST (tny_simple_list_new ());
413 priv->images = TNY_LIST (tny_simple_list_new ());
414 priv->images_size = 0;
415 priv->images_count = 0;
418 priv->cc_caption = NULL;
419 priv->bcc_caption = NULL;
420 priv->update_caption_visibility = FALSE;
422 priv->priority_flags = 0;
424 priv->find_toolbar = NULL;
425 priv->last_search = NULL;
427 priv->draft_msg = NULL;
428 priv->outbox_msg = NULL;
429 priv->msg_uid = NULL;
431 priv->can_undo = FALSE;
432 priv->can_redo = FALSE;
433 priv->clipboard_change_handler_id = 0;
434 priv->default_clipboard_change_handler_id = 0;
435 priv->account_removed_handler_id = 0;
436 priv->clipboard_owner_idle = 0;
437 priv->clipboard_text = NULL;
440 priv->scroll_drag_timeout_id = 0;
441 priv->last_upper = 0.0;
443 priv->font_dialog = NULL;
444 priv->app_menu = NULL;
446 if (!is_wp_text_buffer_started) {
447 is_wp_text_buffer_started = TRUE;
448 wp_text_buffer_library_init ();
453 hildon_program_add_window (hildon_program_get_instance(),
459 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
461 static ModestPairList*
462 get_transports (void)
464 GSList *transports = NULL;
466 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
467 GSList *accounts = modest_account_mgr_account_names (account_mgr,
468 TRUE /* only enabled accounts. */);
470 GSList *cursor = accounts;
472 gchar *account_name = cursor->data;
473 gchar *from_string = NULL;
475 from_string = modest_account_mgr_get_from_string (account_mgr,
479 if (from_string && account_name) {
480 gchar *name = account_name;
481 ModestPair *pair = modest_pair_new ((gpointer) name,
482 (gpointer) from_string , TRUE);
483 transports = g_slist_prepend (transports, pair);
486 cursor = cursor->next;
488 g_slist_free (accounts); /* only free the accounts, not the elements,
489 * because they are used in the pairlist */
493 static void window_focus (GtkWindow *window,
497 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
501 scroll_drag_timeout (gpointer userdata)
503 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
504 ModestMsgEditWindowPrivate *priv;
506 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
508 correct_scroll_without_drag_check (win, TRUE);
510 priv->scroll_drag_timeout_id = 0;
516 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
518 ModestMsgEditWindowPrivate *priv;
521 GdkRectangle rectangle;
525 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
527 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
530 insert = gtk_text_buffer_get_insert (priv->text_buffer);
531 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
533 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
534 offset = priv->msg_body->allocation.y;
536 new_value = (offset + rectangle.y);
538 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (priv->pannable), -1, new_value);
542 correct_scroll (ModestMsgEditWindow *w)
544 ModestMsgEditWindowPrivate *priv;
546 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
547 if (gtk_grab_get_current () == priv->msg_body) {
548 if (priv->scroll_drag_timeout_id == 0) {
549 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
555 correct_scroll_without_drag_check (w, TRUE);
559 text_buffer_end_user_action (GtkTextBuffer *buffer,
560 ModestMsgEditWindow *userdata)
563 correct_scroll (userdata);
567 text_buffer_mark_set (GtkTextBuffer *buffer,
570 ModestMsgEditWindow *userdata)
572 gtk_text_buffer_begin_user_action (buffer);
573 gtk_text_buffer_end_user_action (buffer);
577 cut_clipboard_check (GtkTextView *text_view,
580 GtkTextBuffer *buffer;
582 buffer = gtk_text_view_get_buffer (text_view);
583 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
584 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
589 copy_clipboard_check (GtkTextView *text_view,
592 GtkTextBuffer *buffer;
594 buffer = gtk_text_view_get_buffer (text_view);
595 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
596 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
601 attachment_deleted (ModestAttachmentsView *attachments_view,
604 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
609 connect_signals (ModestMsgEditWindow *obj)
611 ModestMsgEditWindowPrivate *priv;
613 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
615 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
616 G_CALLBACK (text_buffer_refresh_attributes), obj);
617 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
618 G_CALLBACK (text_buffer_can_undo), obj);
619 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
620 G_CALLBACK (text_buffer_can_redo), obj);
621 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
622 G_CALLBACK (body_changed), obj);
623 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
624 G_CALLBACK (body_changed), obj);
625 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
626 G_CALLBACK (text_buffer_end_user_action), obj);
627 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
628 G_CALLBACK (text_buffer_mark_set), obj);
629 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
630 G_CALLBACK (text_buffer_apply_tag), obj);
631 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
632 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
633 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
634 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
635 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
636 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
638 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
639 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
641 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
642 G_CALLBACK (msg_body_focus), obj);
643 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
644 G_CALLBACK (msg_body_focus), obj);
645 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
646 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
647 "changed", G_CALLBACK (recpt_field_changed), obj);
648 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
649 "changed", G_CALLBACK (recpt_field_changed), obj);
650 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
651 "changed", G_CALLBACK (recpt_field_changed), obj);
652 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
653 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
654 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
656 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
657 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
659 priv->clipboard_change_handler_id =
660 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
661 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
662 priv->default_clipboard_change_handler_id =
663 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
664 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
666 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
667 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
668 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
672 init_wp_text_view_style ()
674 static gboolean initialized = FALSE;
677 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
683 init_window (ModestMsgEditWindow *obj)
685 GtkWidget *to_caption, *subject_caption;
686 GtkWidget *main_vbox;
687 ModestMsgEditWindowPrivate *priv;
688 GtkActionGroup *action_group;
689 ModestWindowPrivate *parent_priv;
690 GdkPixbuf *window_icon = NULL;
691 GError *error = NULL;
693 GtkSizeGroup *title_size_group;
694 GtkSizeGroup *value_size_group;
695 GtkWidget *subject_box;
696 GtkWidget *attachment_icon;
697 GtkWidget *window_box;
698 #if (GTK_MINOR_VERSION >= 10)
699 GdkAtom deserialize_type;
702 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
703 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
705 parent_priv->ui_manager = gtk_ui_manager_new();
706 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
707 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
709 /* Add common actions */
710 gtk_action_group_add_actions (action_group,
711 modest_msg_edit_action_entries,
712 G_N_ELEMENTS (modest_msg_edit_action_entries),
714 gtk_action_group_add_actions (action_group,
715 hildon2_msg_edit_action_entries,
716 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
718 gtk_action_group_add_toggle_actions (action_group,
719 modest_msg_edit_toggle_action_entries,
720 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
722 gtk_action_group_add_radio_actions (action_group,
723 modest_msg_edit_alignment_radio_action_entries,
724 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
726 G_CALLBACK (modest_ui_actions_on_change_justify),
728 gtk_action_group_add_radio_actions (action_group,
729 modest_msg_edit_priority_action_entries,
730 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
732 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
734 gtk_action_group_add_radio_actions (action_group,
735 modest_msg_edit_file_format_action_entries,
736 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
737 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
738 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
740 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
741 g_object_unref (action_group);
743 /* Load the UI definition */
744 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
747 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
748 g_clear_error (&error);
751 /* Add accelerators */
752 gtk_window_add_accel_group (GTK_WINDOW (obj),
753 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
755 parent_priv->menubar = NULL;
757 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
758 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
760 /* Note: This ModestPairList* must exist for as long as the picker
761 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
762 * so it can't know how to manage its memory. */
763 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
764 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
766 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
767 _("mail_va_from"), priv->from_field);
769 priv->to_field = modest_recpt_editor_new ();
770 priv->cc_field = modest_recpt_editor_new ();
771 priv->bcc_field = modest_recpt_editor_new ();
772 subject_box = gtk_hbox_new (FALSE, 0);
773 priv->priority_icon = gtk_image_new ();
774 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
775 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
776 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
777 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
778 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
779 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
780 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
781 priv->add_attachment_button = gtk_button_new ();
782 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
783 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
784 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
785 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 0.5);
786 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
787 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
788 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
789 priv->attachments_view = modest_attachments_view_new (NULL);
791 priv->header_box = gtk_vbox_new (FALSE, 0);
793 to_caption = modest_maemo_utils_create_captioned_with_size_type
794 (title_size_group, value_size_group,
795 _("mail_va_to"), priv->to_field,
796 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
797 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
798 (title_size_group, value_size_group,
799 _("mail_va_cc"), priv->cc_field,
800 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
801 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
802 (title_size_group, value_size_group,
803 _("mail_va_hotfix1"), priv->bcc_field,
804 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
805 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
806 _("mail_va_subject"), subject_box);
807 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
808 _("mail_va_attachment"),
809 priv->attachments_view,
810 HILDON_SIZE_AUTO_WIDTH |
811 HILDON_SIZE_AUTO_HEIGHT);
812 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
813 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
814 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
815 g_object_unref (title_size_group);
816 g_object_unref (value_size_group);
818 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
819 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
820 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
821 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
822 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
823 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
824 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
826 init_wp_text_view_style ();
828 priv->msg_body = wp_text_view_new ();
831 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
832 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
833 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
834 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
835 #if (GTK_MINOR_VERSION >= 10)
836 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
837 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
839 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
840 deserialize_type, TRUE);
842 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
844 priv->find_toolbar = hildon_find_toolbar_new (NULL);
845 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
847 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
849 priv->pannable = hildon_pannable_area_new ();
851 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
853 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
854 priv->frame = gtk_frame_new (NULL);
855 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
857 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), main_vbox);
858 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
860 window_box = gtk_vbox_new (FALSE, 0);
861 gtk_container_add (GTK_CONTAINER(obj), window_box);
863 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
865 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
867 /* Set window icon */
868 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
870 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
871 g_object_unref (window_icon);
876 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
878 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
880 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
881 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
882 priv->clipboard_change_handler_id))
883 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
884 priv->clipboard_change_handler_id);
885 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
886 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
887 priv->default_clipboard_change_handler_id))
888 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
889 priv->default_clipboard_change_handler_id);
891 if (priv->account_removed_handler_id &&
892 g_signal_handler_is_connected (modest_runtime_get_account_store (),
893 priv->account_removed_handler_id))
894 g_signal_handler_disconnect(modest_runtime_get_account_store (),
895 priv->account_removed_handler_id);
899 modest_msg_edit_window_finalize (GObject *obj)
901 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
903 /* Sanity check: shouldn't be needed, the window mgr should
904 call this function before */
905 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
907 if (priv->font_dialog != NULL) {
908 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
911 if (priv->clipboard_text != NULL) {
912 g_free (priv->clipboard_text);
913 priv->clipboard_text = NULL;
916 if (priv->draft_msg != NULL) {
917 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
918 if (TNY_IS_HEADER (header)) {
919 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
920 modest_window_mgr_unregister_header (mgr, header);
922 g_object_unref (priv->draft_msg);
923 priv->draft_msg = NULL;
925 if (priv->outbox_msg != NULL) {
926 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
927 if (TNY_IS_HEADER (header)) {
928 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
929 modest_window_mgr_unregister_header (mgr, header);
931 g_object_unref (priv->outbox_msg);
932 priv->outbox_msg = NULL;
934 if (priv->scroll_drag_timeout_id > 0) {
935 g_source_remove (priv->scroll_drag_timeout_id);
936 priv->scroll_drag_timeout_id = 0;
938 if (priv->clipboard_owner_idle > 0) {
939 g_source_remove (priv->clipboard_owner_idle);
940 priv->clipboard_owner_idle = 0;
942 if (priv->original_account_name)
943 g_free (priv->original_account_name);
944 g_free (priv->msg_uid);
945 g_free (priv->last_search);
946 g_slist_free (priv->font_items_group);
947 g_slist_free (priv->size_items_group);
948 g_object_unref (priv->attachments);
949 g_object_unref (priv->images);
951 /* This had to stay alive for as long as the picker that used it: */
952 modest_pair_list_free (priv->from_field_protos);
954 G_OBJECT_CLASS(parent_class)->finalize (obj);
958 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
960 GdkPixbufLoader *loader;
966 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
968 if (loader == NULL) {
974 tny_stream_reset (TNY_STREAM (stream));
975 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
976 GError *error = NULL;
977 unsigned char read_buffer[128];
979 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
981 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
983 g_error_free (error);
988 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
990 g_object_ref (pixbuf);
991 gdk_pixbuf_loader_close (loader, NULL);
992 g_object_unref (loader);
997 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
998 GdkPixbuf *new_pixbuf;
1000 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1001 gdk_pixbuf_get_width (pixbuf);
1002 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1003 g_object_unref (pixbuf);
1004 pixbuf = new_pixbuf;
1008 *stream_size = size;
1014 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1016 ModestMsgEditWindowPrivate *priv;
1019 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1021 for (iter = tny_list_create_iterator (attachments);
1022 !tny_iterator_is_done (iter);
1023 tny_iterator_next (iter)) {
1024 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1025 const gchar *cid = tny_mime_part_get_content_id (part);
1026 const gchar *mime_type = tny_mime_part_get_content_type (part);
1027 if ((cid != NULL)&&(mime_type != NULL)) {
1028 guint64 stream_size;
1029 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1030 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1033 g_object_unref (stream);
1035 if (pixbuf != NULL) {
1036 priv->images_count ++;
1037 priv->images_size += stream_size;
1038 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1039 g_object_unref (pixbuf);
1042 g_object_unref (part);
1044 g_object_unref (iter);
1048 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1050 TnyMimePart *parent = NULL;
1051 const gchar *content_type = NULL;
1052 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1054 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1056 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1057 parent = g_object_ref (msg);
1058 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1059 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1062 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1063 iter = tny_list_create_iterator (parts);
1064 while (!tny_iterator_is_done (iter)) {
1066 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1067 content_type = tny_mime_part_get_content_type (part);
1068 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1072 g_object_unref (part);
1074 tny_iterator_next (iter);
1076 g_object_unref (iter);
1077 g_object_unref (parts);
1080 if (parent != NULL) {
1081 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1084 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1085 iter = tny_list_create_iterator (parts);
1086 while (!tny_iterator_is_done (iter)) {
1088 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1089 content_type = tny_mime_part_get_content_type (part);
1090 if (content_type && g_str_has_prefix (content_type, "image/")) {
1091 tny_list_prepend (priv->images, (GObject *) part);
1093 g_object_unref (part);
1094 tny_iterator_next (iter);
1096 g_object_unref (iter);
1097 g_object_unref (parts);
1098 g_object_unref (parent);
1103 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1106 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1108 for (iter = tny_list_create_iterator (attachments) ;
1109 !tny_iterator_is_done (iter);
1110 tny_iterator_next (iter)) {
1111 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1112 const gchar *cid = tny_mime_part_get_content_id (part);
1114 char *invalid = NULL;
1115 gint int_cid = strtol (cid, &invalid, 10);
1116 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1117 priv->next_cid = int_cid + 1;
1120 g_object_unref (part);
1122 g_object_unref (iter);
1126 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1129 gchar *to, *cc, *bcc, *subject;
1131 ModestMsgEditWindowPrivate *priv;
1132 ModestWindowPrivate *parent_priv;
1134 TnyHeaderFlags priority_flags;
1135 TnyFolder *msg_folder;
1136 gboolean is_html = FALSE;
1138 gboolean field_view_set;
1140 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1141 g_return_if_fail (TNY_IS_MSG (msg));
1143 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1144 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1146 header = tny_msg_get_header (msg);
1147 to = tny_header_dup_to (header);
1148 cc = tny_header_dup_cc (header);
1149 bcc = tny_header_dup_bcc (header);
1150 subject = tny_header_dup_subject (header);
1151 priority_flags = tny_header_get_priority (header);
1154 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1156 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
1157 field_view_set = TRUE;
1159 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1160 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1161 gtk_widget_show (priv->cc_caption);
1162 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1163 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1164 gtk_widget_hide (priv->cc_caption);
1165 field_view_set = FALSE;
1168 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), field_view_set);
1170 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
1171 field_view_set = TRUE;
1173 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1174 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1175 gtk_widget_show (priv->bcc_caption);
1176 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1177 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1178 gtk_widget_hide (priv->bcc_caption);
1179 field_view_set = FALSE;
1182 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), field_view_set);
1186 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1187 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1190 update_window_title (self);
1192 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1193 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1195 if ((body == NULL)||(body[0] == '\0')) {
1197 body = modest_text_utils_convert_to_html ("");
1200 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1201 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1204 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1207 /* Add attachments to the view */
1208 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1209 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1210 if (tny_list_get_length (priv->attachments) == 0) {
1211 gtk_widget_hide (priv->attachments_caption);
1213 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1214 gtk_widget_show_all (priv->attachments_caption);
1216 get_related_images (self, msg);
1217 update_next_cid (self, priv->attachments);
1218 update_next_cid (self, priv->images);
1219 replace_with_images (self, priv->images);
1221 if (preserve_is_rich && !is_html) {
1222 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1223 /* Get the default format required from configuration */
1224 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1225 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1228 /* Set the default focus depending on having already a To: field or not */
1229 if ((!to)||(*to == '\0')) {
1230 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1232 gtk_widget_grab_focus (priv->msg_body);
1235 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1237 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1238 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1240 modest_msg_edit_window_set_modified (self, FALSE);
1242 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1243 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1244 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1245 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1247 if (priv->msg_uid) {
1248 g_free (priv->msg_uid);
1249 priv->msg_uid = NULL;
1252 /* we should set a reference to the incoming message if it is a draft */
1253 msg_folder = tny_msg_get_folder (msg);
1255 if (modest_tny_folder_is_local_folder (msg_folder)) {
1256 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1257 if (type == TNY_FOLDER_TYPE_INVALID)
1258 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1260 if (type == TNY_FOLDER_TYPE_DRAFTS)
1261 priv->draft_msg = g_object_ref(msg);
1262 if (type == TNY_FOLDER_TYPE_OUTBOX)
1263 priv->outbox_msg = g_object_ref(msg);
1264 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1266 g_object_unref (msg_folder);
1276 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1279 GList *item_children, *node;
1280 GtkWidget *bin_child;
1282 bin_child = gtk_bin_get_child (GTK_BIN(item));
1284 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1286 for (node = item_children; node != NULL; node = g_list_next (node)) {
1287 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1288 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1291 g_list_free (item_children);
1295 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1298 GList *item_children, *node;
1300 box = gtk_bin_get_child (GTK_BIN (item));
1301 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1302 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1304 for (node = item_children; node != NULL; node = g_list_next (node)) {
1305 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1306 if (GTK_IS_TOGGLE_BUTTON (node->data))
1307 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1308 else if (GTK_IS_BUTTON (node->data))
1309 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1311 g_list_free (item_children);
1316 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1318 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1319 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1320 GtkWidget *placeholder;
1321 GtkWidget *tool_item;
1326 GtkWidget *sizes_menu;
1327 GtkWidget *fonts_menu;
1328 GSList *radio_group = NULL;
1329 GSList *node = NULL;
1333 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1334 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1336 /* Font color placeholder */
1337 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1338 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1341 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1342 priv->font_color_button = hildon_color_button_new ();
1343 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1344 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1345 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1346 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1347 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1348 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1349 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1351 G_CALLBACK (modest_msg_edit_window_color_button_change),
1354 /* Font size and face placeholder */
1355 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1356 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1358 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1359 priv->size_tool_button_label = gtk_label_new (NULL);
1360 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1361 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1362 size_text,"</span>", NULL);
1363 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1365 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1366 sizes_menu = gtk_menu_new ();
1367 priv->size_items_group = NULL;
1369 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1370 GtkWidget *size_menu_item;
1372 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1373 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1374 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1375 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1376 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1377 gtk_widget_show (size_menu_item);
1379 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1383 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1384 GtkWidget *item = (GtkWidget *) node->data;
1385 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1389 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1390 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1391 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1392 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1393 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1394 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1395 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1396 priv->font_size_toolitem = tool_item;
1399 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1400 priv->font_tool_button_label = gtk_label_new (NULL);
1401 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1402 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1404 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1405 fonts_menu = gtk_menu_new ();
1406 priv->font_items_group = NULL;
1408 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1409 GtkWidget *font_menu_item;
1410 GtkWidget *child_label;
1412 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1413 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1414 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1415 wp_get_font_name (font_index), "</span>", NULL);
1416 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1419 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1420 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1421 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1422 gtk_widget_show (font_menu_item);
1424 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1427 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1428 GtkWidget *item = (GtkWidget *) node->data;
1429 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1432 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1433 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1434 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1435 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1436 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1437 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1438 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1439 priv->font_face_toolitem = tool_item;
1441 /* Set expand and homogeneous for remaining items */
1442 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1443 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1444 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1445 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1446 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1447 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1448 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1449 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1450 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1452 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1453 will not show the tool items added to the placeholders) */
1454 gtk_widget_show_all (parent_priv->toolbar);
1456 /* Set the no show all *after* showing all items. We do not
1457 want the toolbar to be shown with a show all because it
1458 could go agains the gconf setting regarding showing or not
1459 the toolbar of the editor window */
1460 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1466 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1469 ModestWindowPrivate *parent_priv;
1470 ModestMsgEditWindowPrivate *priv;
1471 ModestDimmingRulesGroup *menu_rules_group = NULL;
1472 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1473 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1474 ModestWindowMgr *mgr = NULL;
1476 g_return_val_if_fail (msg, NULL);
1477 g_return_val_if_fail (account_name, NULL);
1479 mgr = modest_runtime_get_window_mgr ();
1481 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1483 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1484 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1486 /* Menubar. Update the state of some toggles */
1487 priv->from_field_protos = get_transports ();
1488 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1489 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1490 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1492 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1493 hildon_touch_selector_get_current_text
1494 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1495 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1496 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1499 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1501 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1503 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1505 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1507 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1508 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1509 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1510 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1511 /* Add common dimming rules */
1512 modest_dimming_rules_group_add_rules (menu_rules_group,
1513 modest_msg_edit_window_menu_dimming_entries,
1514 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1515 MODEST_WINDOW (obj));
1516 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1517 modest_msg_edit_window_toolbar_dimming_entries,
1518 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1519 MODEST_WINDOW (obj));
1520 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1521 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1522 MODEST_WINDOW (obj));
1523 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1524 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1525 MODEST_WINDOW (obj));
1526 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1527 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1528 MODEST_WINDOW (obj));
1529 /* Insert dimming rules group for this window */
1530 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1531 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1532 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1534 /* Setup app menu */
1535 setup_menu (MODEST_MSG_EDIT_WINDOW (obj), menu_rules_group);
1537 /* Checks the dimming rules */
1538 g_object_unref (menu_rules_group);
1539 g_object_unref (toolbar_rules_group);
1540 g_object_unref (clipboard_rules_group);
1541 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1543 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1545 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1546 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1547 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1548 priv->update_caption_visibility = TRUE;
1550 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1552 /* Track account-removed signal, this window should be closed
1553 in the case we're creating a mail associated to the account
1555 priv->account_removed_handler_id =
1556 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1558 G_CALLBACK(on_account_removed),
1561 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1563 return (ModestWindow*) obj;
1567 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1569 GString **string_buffer = (GString **) user_data;
1571 *string_buffer = g_string_append (*string_buffer, buffer);
1577 * @result: A new string which should be freed with g_free().
1580 get_formatted_data (ModestMsgEditWindow *edit_window)
1582 ModestMsgEditWindowPrivate *priv;
1583 GString *string_buffer = g_string_new ("");
1585 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1587 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1589 modest_text_utils_hyperlinkify (string_buffer);
1591 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1593 return g_string_free (string_buffer, FALSE);
1598 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1601 const gchar *account_name;
1602 ModestMsgEditWindowPrivate *priv;
1603 TnyIterator *att_iter;
1605 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1607 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1609 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1610 g_return_val_if_fail (account_name, NULL);
1613 /* don't free these (except from) */
1614 data = g_slice_new0 (MsgData);
1615 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1617 data->account_name = g_strdup (account_name);
1618 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1619 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1620 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1621 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1622 if (priv->draft_msg) {
1623 data->draft_msg = g_object_ref (priv->draft_msg);
1624 } else if (priv->outbox_msg) {
1625 data->draft_msg = g_object_ref (priv->outbox_msg);
1627 data->draft_msg = NULL;
1630 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1632 gtk_text_buffer_get_bounds (buf, &b, &e);
1633 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1635 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1636 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1638 data->html_body = NULL;
1640 /* deep-copy the data */
1641 att_iter = tny_list_create_iterator (priv->attachments);
1642 data->attachments = NULL;
1643 while (!tny_iterator_is_done (att_iter)) {
1644 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1645 if (!(TNY_IS_MIME_PART(part))) {
1646 g_warning ("strange data in attachment list");
1647 g_object_unref (part);
1648 tny_iterator_next (att_iter);
1651 data->attachments = g_list_append (data->attachments,
1653 tny_iterator_next (att_iter);
1655 g_object_unref (att_iter);
1657 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1658 att_iter = tny_list_create_iterator (priv->images);
1659 data->images = NULL;
1660 while (!tny_iterator_is_done (att_iter)) {
1661 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1663 if (!(TNY_IS_MIME_PART(part))) {
1664 g_warning ("strange data in attachment list");
1665 g_object_unref (part);
1666 tny_iterator_next (att_iter);
1669 cid = tny_mime_part_get_content_id (part);
1671 gchar *image_tag_id;
1672 GtkTextTag *image_tag;
1674 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1675 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1676 g_free (image_tag_id);
1678 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1680 ((gtk_text_iter_has_tag (&iter, image_tag))||
1681 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1682 data->images = g_list_append (data->images,
1683 g_object_ref (part));
1685 g_object_unref (part);
1686 tny_iterator_next (att_iter);
1688 g_object_unref (att_iter);
1690 data->priority_flags = priv->priority_flags;
1697 unref_gobject (GObject *obj, gpointer data)
1699 if (!G_IS_OBJECT(obj))
1701 g_object_unref (obj);
1705 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1708 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1716 g_free (data->from);
1717 g_free (data->subject);
1718 g_free (data->plain_body);
1719 g_free (data->html_body);
1720 g_free (data->account_name);
1722 if (data->draft_msg != NULL) {
1723 g_object_unref (data->draft_msg);
1724 data->draft_msg = NULL;
1727 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1728 g_list_free (data->attachments);
1729 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1730 g_list_free (data->images);
1732 g_slice_free (MsgData, data);
1736 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1738 guint64 *parts_size)
1740 ModestMsgEditWindowPrivate *priv;
1742 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1744 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1746 /* TODO: add images */
1747 *parts_size += priv->images_size;
1748 *parts_count += priv->images_count;
1753 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1756 ModestMsgEditWindowPrivate *priv = NULL;
1757 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1759 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1761 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1763 return MODEST_MSG_EDIT_FORMAT_HTML;
1765 return MODEST_MSG_EDIT_FORMAT_TEXT;
1769 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1770 ModestMsgEditFormat format)
1772 ModestMsgEditWindowPrivate *priv;
1774 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1775 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1778 case MODEST_MSG_EDIT_FORMAT_HTML:
1779 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1781 case MODEST_MSG_EDIT_FORMAT_TEXT:
1782 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1785 g_return_if_reached ();
1789 ModestMsgEditFormatState *
1790 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1792 ModestMsgEditFormatState *format_state = NULL;
1793 ModestMsgEditWindowPrivate *priv;
1794 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1796 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1797 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1799 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1801 format_state = g_new0 (ModestMsgEditFormatState, 1);
1802 format_state->bold = buffer_format->bold&0x1;
1803 format_state->italics = buffer_format->italic&0x1;
1804 format_state->bullet = buffer_format->bullet&0x1;
1805 format_state->color = buffer_format->color;
1806 format_state->font_size = buffer_format->font_size;
1807 format_state->font_family = wp_get_font_name (buffer_format->font);
1808 format_state->justification = buffer_format->justification;
1809 g_free (buffer_format);
1811 return format_state;
1816 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1817 const ModestMsgEditFormatState *format_state)
1819 ModestMsgEditWindowPrivate *priv;
1820 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1821 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1822 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1823 g_return_if_fail (format_state != NULL);
1825 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1826 gtk_widget_grab_focus (priv->msg_body);
1827 buffer_format->bold = (format_state->bold != FALSE);
1828 buffer_format->italic = (format_state->italics != FALSE);
1829 buffer_format->color = format_state->color;
1830 buffer_format->font_size = format_state->font_size;
1831 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1832 buffer_format->justification = format_state->justification;
1833 buffer_format->bullet = format_state->bullet;
1835 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1837 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1838 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1839 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1840 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1841 buffer_format->cs.font = (buffer_format->font != current_format->font);
1842 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1843 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1845 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1846 if (buffer_format->cs.bold) {
1847 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1848 GINT_TO_POINTER (buffer_format->bold&0x1));
1850 if (buffer_format->cs.italic) {
1851 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1852 GINT_TO_POINTER (buffer_format->italic&0x1));
1854 if (buffer_format->cs.color) {
1855 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1856 GINT_TO_POINTER (&(buffer_format->color)));
1858 if (buffer_format->cs.font_size) {
1859 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1860 GINT_TO_POINTER (buffer_format->font_size));
1862 if (buffer_format->cs.justification) {
1863 switch (buffer_format->justification) {
1864 case GTK_JUSTIFY_LEFT:
1865 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1866 GINT_TO_POINTER(TRUE));
1868 case GTK_JUSTIFY_CENTER:
1869 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1870 GINT_TO_POINTER(TRUE));
1872 case GTK_JUSTIFY_RIGHT:
1873 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1874 GINT_TO_POINTER(TRUE));
1881 if (buffer_format->cs.font) {
1882 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1883 GINT_TO_POINTER (buffer_format->font));
1885 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1886 if (buffer_format->cs.bullet) {
1887 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1888 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1890 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1892 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1894 g_free (buffer_format);
1895 g_free (current_format);
1897 /* Check dimming rules */
1898 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1899 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1903 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1905 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1907 ModestWindowPrivate *parent_priv;
1908 ModestMsgEditWindowPrivate *priv;
1909 GtkWidget *new_size_menuitem;
1910 GtkWidget *new_font_menuitem;
1912 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1913 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1915 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1916 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1917 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1918 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1920 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1921 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1922 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1925 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1927 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1928 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1930 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1931 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1933 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1934 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1937 switch (buffer_format->justification)
1939 case GTK_JUSTIFY_LEFT:
1940 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1942 case GTK_JUSTIFY_CENTER:
1943 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1945 case GTK_JUSTIFY_RIGHT:
1946 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1953 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1955 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1956 G_CALLBACK (modest_msg_edit_window_color_button_change),
1958 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1959 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1960 G_CALLBACK (modest_msg_edit_window_color_button_change),
1963 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1964 buffer_format->font_size))->data);
1965 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1969 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1970 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1971 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1973 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1974 G_CALLBACK (modest_msg_edit_window_size_change),
1976 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1977 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1978 G_CALLBACK (modest_msg_edit_window_size_change),
1982 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1983 buffer_format->font))->data);
1984 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1988 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1989 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1990 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1992 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1993 G_CALLBACK (modest_msg_edit_window_font_change),
1995 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1996 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1997 G_CALLBACK (modest_msg_edit_window_font_change),
2001 g_free (buffer_format);
2005 #ifdef MODEST_HILDON_VERSION_0
2007 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2010 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2011 ModestMsgEditWindowPrivate *priv;
2012 GtkWidget *dialog = NULL;
2014 GdkColor *new_color = NULL;
2016 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2017 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2019 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2020 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2021 g_free (buffer_format);
2023 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2024 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2025 if (new_color != NULL) {
2026 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2027 (gpointer) new_color);
2030 gtk_widget_destroy (dialog);
2035 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2038 ModestMsgEditWindowPrivate *priv;
2039 GtkWidget *dialog = NULL;
2041 GdkColor *old_color = NULL;
2042 const GdkColor *new_color = NULL;
2044 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2045 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2047 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2048 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2050 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2051 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2052 if (new_color != NULL)
2053 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2055 gtk_widget_destroy (dialog);
2061 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2064 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2065 ModestMsgEditWindowPrivate *priv;
2066 GtkWidget *dialog = NULL;
2068 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2069 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2071 dialog = hildon_color_chooser_new ();
2072 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2073 g_free (buffer_format);
2075 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2077 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2078 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2081 gtk_widget_destroy (dialog);
2086 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2089 ModestMsgEditWindowPrivate *priv;
2090 GtkWidget *dialog = NULL;
2091 GdkColor *old_color = NULL;
2093 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2094 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2096 dialog = hildon_color_chooser_new ();
2097 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2099 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2101 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2102 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2104 gtk_widget_destroy (dialog);
2107 #endif /*!MODEST_HILDON_VERSION_0*/
2112 create_stream_for_uri (const gchar* uri)
2117 TnyStream *result = NULL;
2119 GnomeVFSHandle *handle = NULL;
2120 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2121 if (test == GNOME_VFS_OK) {
2122 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2123 /* Streams over OBEX (Bluetooth) are not seekable but
2124 * we expect them to be (we might need to read them
2125 * several times). So if this is a Bluetooth URI just
2126 * read the whole file into memory (this is not a fast
2127 * protocol so we can assume that these files are not
2128 * going to be very big) */
2129 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2130 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2131 TnyStream *memstream = tny_camel_mem_stream_new ();
2132 tny_stream_write_to_stream (vfssstream, memstream);
2133 g_object_unref (vfssstream);
2136 result = vfssstream;
2144 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2147 ModestMsgEditWindowPrivate *priv;
2148 GtkWidget *dialog = NULL;
2150 GSList *uris = NULL;
2151 GSList *uri_node = NULL;
2153 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2155 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2156 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2157 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2159 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2161 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2162 GTK_WINDOW (dialog), GTK_WINDOW (window));
2164 response = gtk_dialog_run (GTK_DIALOG (dialog));
2166 case GTK_RESPONSE_OK:
2167 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2172 gtk_widget_destroy (dialog);
2174 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2176 GnomeVFSHandle *handle = NULL;
2177 GnomeVFSResult result;
2178 GtkTextIter position;
2179 GtkTextMark *insert_mark;
2181 uri = (const gchar *) uri_node->data;
2182 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2183 if (result == GNOME_VFS_OK) {
2185 GnomeVFSFileInfo *info;
2186 gchar *filename, *basename, *escaped_filename;
2187 TnyMimePart *mime_part;
2189 const gchar *mime_type = NULL;
2190 GnomeVFSURI *vfs_uri;
2191 guint64 stream_size;
2193 gnome_vfs_close (handle);
2194 vfs_uri = gnome_vfs_uri_new (uri);
2196 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2197 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2198 g_free (escaped_filename);
2199 gnome_vfs_uri_unref (vfs_uri);
2200 info = gnome_vfs_file_info_new ();
2202 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2203 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2205 mime_type = gnome_vfs_file_info_get_mime_type (info);
2207 mime_part = tny_platform_factory_new_mime_part
2208 (modest_runtime_get_platform_factory ());
2210 TnyStream *stream = create_stream_for_uri (uri);
2212 if (stream == NULL) {
2214 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2216 g_object_unref (mime_part);
2217 gnome_vfs_file_info_unref (info);
2221 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2223 content_id = g_strdup_printf ("%d", priv->next_cid);
2224 tny_mime_part_set_content_id (mime_part, content_id);
2225 g_free (content_id);
2228 basename = g_path_get_basename (filename);
2229 tny_mime_part_set_filename (mime_part, basename);
2232 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2234 if (pixbuf != NULL) {
2235 priv->images_size += stream_size;
2236 priv->images_count ++;
2237 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2238 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2239 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2240 g_object_unref (pixbuf);
2243 tny_list_prepend (priv->images, (GObject *) mime_part);
2244 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2246 g_object_unref (mime_part);
2247 gnome_vfs_file_info_unref (info);
2256 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2258 GtkWidget *dialog = NULL;
2260 GSList *uris = NULL;
2262 GnomeVFSFileSize total_size, allowed_size;
2263 ModestMsgEditWindowPrivate *priv;
2267 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2269 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2271 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2274 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2275 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2276 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2277 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), GTK_WINDOW (window));
2279 response = gtk_dialog_run (GTK_DIALOG (dialog));
2281 case GTK_RESPONSE_OK:
2282 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2287 gtk_widget_destroy (dialog);
2289 /* allowed size is the maximum size - what's already there */
2290 modest_attachments_view_get_sizes (
2291 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2292 &att_num, &att_size);
2293 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2296 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2298 const gchar *uri = (const gchar *) uri_node->data;
2300 total_size += modest_msg_edit_window_attach_file_one
2301 (window, uri, allowed_size);
2303 if (total_size > allowed_size) {
2304 g_warning ("%s: total size: %u",
2305 __FUNCTION__, (unsigned int)total_size);
2309 allowed_size -= total_size;
2313 g_slist_foreach (uris, (GFunc) g_free, NULL);
2314 g_slist_free (uris);
2319 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2321 GnomeVFSFileSize allowed_size)
2324 GnomeVFSHandle *handle = NULL;
2325 ModestMsgEditWindowPrivate *priv;
2326 GnomeVFSResult result;
2327 GnomeVFSFileSize size = 0;
2328 g_return_val_if_fail (window, 0);
2329 g_return_val_if_fail (uri, 0);
2331 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2333 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2334 if (result == GNOME_VFS_OK) {
2335 TnyMimePart *mime_part;
2337 const gchar *mime_type = NULL;
2339 gchar *escaped_filename;
2342 GnomeVFSFileInfo *info;
2343 GnomeVFSURI *vfs_uri;
2345 gnome_vfs_close (handle);
2346 vfs_uri = gnome_vfs_uri_new (uri);
2349 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2350 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2351 g_free (escaped_filename);
2352 gnome_vfs_uri_unref (vfs_uri);
2354 info = gnome_vfs_file_info_new ();
2356 if (gnome_vfs_get_file_info (uri,
2358 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2360 mime_type = gnome_vfs_file_info_get_mime_type (info);
2361 mime_part = tny_platform_factory_new_mime_part
2362 (modest_runtime_get_platform_factory ());
2364 /* try to get the attachment's size; this may fail for weird
2365 * file systems, like obex, upnp... */
2366 if (allowed_size != 0 &&
2367 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2369 if (size > allowed_size) {
2370 modest_platform_information_banner (NULL, NULL,
2371 dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2375 g_warning ("%s: could not get attachment size", __FUNCTION__);
2377 stream = create_stream_for_uri (uri);
2379 if (stream == NULL) {
2381 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2383 g_object_unref (mime_part);
2384 gnome_vfs_file_info_unref (info);
2388 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2389 g_object_unref (stream);
2391 content_id = g_strdup_printf ("%d", priv->next_cid);
2392 tny_mime_part_set_content_id (mime_part, content_id);
2393 g_free (content_id);
2396 basename = g_path_get_basename (filename);
2397 tny_mime_part_set_filename (mime_part, basename);
2400 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2401 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2403 info->size == 0, info->size);
2404 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2405 gtk_widget_show_all (priv->attachments_caption);
2406 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2408 g_object_unref (mime_part);
2409 gnome_vfs_file_info_unref (info);
2416 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2419 ModestMsgEditWindowPrivate *priv;
2422 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2423 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2425 if (att_list == NULL) {
2426 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2428 g_object_ref (att_list);
2431 if (tny_list_get_length (att_list) == 0) {
2432 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2434 gboolean dialog_response;
2435 gchar *message = NULL;
2436 gchar *filename = NULL;
2438 if (tny_list_get_length (att_list) == 1) {
2440 iter = tny_list_create_iterator (att_list);
2441 part = (TnyMimePart *) tny_iterator_get_current (iter);
2442 g_object_unref (iter);
2443 if (TNY_IS_MSG (part)) {
2444 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2446 filename = tny_header_dup_subject (header);
2447 g_object_unref (header);
2449 if (filename == NULL) {
2450 filename = g_strdup (_("mail_va_no_subject"));
2453 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2455 g_object_unref (part);
2457 filename = g_strdup ("");
2459 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2460 tny_list_get_length (att_list)), filename);
2463 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2466 if (dialog_response != GTK_RESPONSE_OK) {
2467 g_object_unref (att_list);
2470 hildon_banner_show_information (NULL, NULL, _("mcen_me_inbox_remove_attachments"));
2472 for (iter = tny_list_create_iterator (att_list);
2473 !tny_iterator_is_done (iter);
2474 tny_iterator_next (iter)) {
2475 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2476 const gchar *att_id;
2477 tny_list_remove (priv->attachments, (GObject *) mime_part);
2479 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2481 if (tny_list_get_length (priv->attachments) == 0)
2482 gtk_widget_hide (priv->attachments_caption);
2483 att_id = tny_mime_part_get_content_id (mime_part);
2485 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2487 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2488 g_object_unref (mime_part);
2490 g_object_unref (iter);
2493 g_object_unref (att_list);
2495 /* if the last attachment has been removed, focus the Subject: field */
2496 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2497 gtk_widget_grab_focus (priv->subject_field);
2501 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2504 ModestMsgEditWindowPrivate *priv;
2505 GdkColor *new_color;
2506 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2508 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2509 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2512 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2514 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2516 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2518 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2523 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2526 ModestMsgEditWindowPrivate *priv;
2527 gint new_size_index;
2528 ModestMsgEditWindow *window;
2531 window = MODEST_MSG_EDIT_WINDOW (userdata);
2532 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2533 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2535 if (gtk_check_menu_item_get_active (menu_item)) {
2537 WPTextBufferFormat format;
2539 memset (&format, 0, sizeof (format));
2540 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2542 label = gtk_bin_get_child (GTK_BIN (menu_item));
2544 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2545 format.cs.font_size = TRUE;
2546 format.cs.text_position = TRUE;
2547 format.cs.font = TRUE;
2548 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2549 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2551 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2552 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2553 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2555 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2556 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2557 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2563 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2566 ModestMsgEditWindowPrivate *priv;
2567 gint new_font_index;
2568 ModestMsgEditWindow *window;
2571 window = MODEST_MSG_EDIT_WINDOW (userdata);
2572 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2573 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2575 if (gtk_check_menu_item_get_active (menu_item)) {
2578 label = gtk_bin_get_child (GTK_BIN (menu_item));
2580 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2582 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2583 GINT_TO_POINTER(new_font_index)))
2584 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2586 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2587 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2588 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2594 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2597 ModestMsgEditWindowPrivate *priv = NULL;
2598 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2600 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2601 if (!priv->update_caption_visibility)
2604 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2606 gtk_widget_show (priv->cc_caption);
2608 gtk_widget_hide (priv->cc_caption);
2610 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2614 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2617 ModestMsgEditWindowPrivate *priv = NULL;
2618 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2620 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2621 if (!priv->update_caption_visibility)
2624 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2626 gtk_widget_show (priv->bcc_caption);
2628 gtk_widget_hide (priv->bcc_caption);
2630 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2634 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2635 ModestRecptEditor *editor)
2637 ModestMsgEditWindowPrivate *priv;
2639 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2640 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2642 /* we check for low-mem; in that case, show a warning, and don't allow
2643 * for the addressbook
2645 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2648 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2650 if (editor == NULL) {
2651 GtkWidget *view_focus;
2652 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2654 /* This code should be kept in sync with ModestRecptEditor. The
2655 textview inside the recpt editor is the one that really gets the
2656 focus. As it's inside a scrolled window, and this one inside the
2657 hbox recpt editor inherits from, we'll need to go up in the
2658 hierarchy to know if the text view is part of the recpt editor
2659 or if it's a different text entry */
2661 if (gtk_widget_get_parent (view_focus)) {
2662 GtkWidget *first_parent;
2664 first_parent = gtk_widget_get_parent (view_focus);
2665 if (gtk_widget_get_parent (first_parent) &&
2666 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2667 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2672 editor = MODEST_RECPT_EDITOR (priv->to_field);
2676 modest_address_book_select_addresses (editor);
2681 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2683 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2685 modest_msg_edit_window_open_addressbook (window, NULL);
2689 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2690 gboolean show_toolbar)
2692 ModestWindowPrivate *parent_priv;
2694 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2695 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2697 /* We can not just use the code of
2698 modest_msg_edit_window_setup_toolbar because it has a
2699 mixture of both initialization and creation code. */
2701 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2703 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2707 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2708 TnyHeaderFlags priority_flags)
2710 ModestMsgEditWindowPrivate *priv;
2711 ModestWindowPrivate *parent_priv;
2713 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2715 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2716 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2718 if (priv->priority_flags != priority_flags) {
2719 GtkAction *priority_action = NULL;
2721 priv->priority_flags = priority_flags;
2723 switch (priority_flags) {
2724 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2725 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2726 MODEST_HEADER_ICON_HIGH,
2727 HILDON_ICON_SIZE_XSMALL);
2728 gtk_widget_show (priv->priority_icon);
2729 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2730 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2732 case TNY_HEADER_FLAG_LOW_PRIORITY:
2733 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2734 MODEST_HEADER_ICON_LOW,
2735 HILDON_ICON_SIZE_XSMALL);
2736 gtk_widget_show (priv->priority_icon);
2737 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2738 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2741 gtk_widget_hide (priv->priority_icon);
2742 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2743 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2746 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2747 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2752 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2755 ModestMsgEditWindowPrivate *priv;
2756 ModestWindowPrivate *parent_priv;
2757 gint current_format;
2759 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2761 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2762 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2764 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2765 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2767 if (current_format != file_format) {
2768 switch (file_format) {
2769 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2770 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2771 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2773 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2777 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2778 response = gtk_dialog_run (GTK_DIALOG (dialog));
2779 gtk_widget_destroy (dialog);
2780 if (response == GTK_RESPONSE_OK) {
2781 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2783 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2784 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2789 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2790 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2791 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2796 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2799 ModestMsgEditWindowPrivate *priv;
2800 WPTextBufferFormat oldfmt, fmt;
2801 gint old_position = 0;
2805 GdkColor *color = NULL;
2806 gboolean bold, bold_set, italic, italic_set;
2807 gboolean underline, underline_set;
2808 gboolean strikethrough, strikethrough_set;
2809 gboolean position_set;
2810 gboolean font_size_set, font_set, color_set;
2813 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2814 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2816 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2817 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2818 GTK_WINDOW(dialog), GTK_WINDOW (window));
2820 /* First we get the currently selected font information */
2821 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2823 switch (oldfmt.text_position) {
2824 case TEXT_POSITION_NORMAL:
2827 case TEXT_POSITION_SUPERSCRIPT:
2835 g_object_set (G_OBJECT (dialog),
2836 "bold", oldfmt.bold != FALSE,
2837 "bold-set", !oldfmt.cs.bold,
2838 "underline", oldfmt.underline != FALSE,
2839 "underline-set", !oldfmt.cs.underline,
2840 "italic", oldfmt.italic != FALSE,
2841 "italic-set", !oldfmt.cs.italic,
2842 "strikethrough", oldfmt.strikethrough != FALSE,
2843 "strikethrough-set", !oldfmt.cs.strikethrough,
2844 "color", &oldfmt.color,
2845 "color-set", !oldfmt.cs.color,
2846 "size", wp_font_size[oldfmt.font_size],
2847 "size-set", !oldfmt.cs.font_size,
2848 "position", old_position,
2849 "position-set", !oldfmt.cs.text_position,
2850 "family", wp_get_font_name (oldfmt.font),
2851 "family-set", !oldfmt.cs.font,
2854 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2855 GTK_WINDOW (dialog), GTK_WINDOW (window));
2856 gtk_widget_show_all (dialog);
2857 priv->font_dialog = dialog;
2858 response = gtk_dialog_run (GTK_DIALOG (dialog));
2859 priv->font_dialog = NULL;
2860 if (response == GTK_RESPONSE_OK) {
2862 g_object_get( dialog,
2864 "bold-set", &bold_set,
2865 "underline", &underline,
2866 "underline-set", &underline_set,
2868 "italic-set", &italic_set,
2869 "strikethrough", &strikethrough,
2870 "strikethrough-set", &strikethrough_set,
2872 "color-set", &color_set,
2874 "size-set", &font_size_set,
2875 "family", &font_name,
2876 "family-set", &font_set,
2877 "position", &position,
2878 "position-set", &position_set,
2883 if (response == GTK_RESPONSE_OK) {
2884 memset(&fmt, 0, sizeof(fmt));
2890 fmt.italic = italic;
2891 fmt.cs.italic = TRUE;
2893 if (underline_set) {
2894 fmt.underline = underline;
2895 fmt.cs.underline = TRUE;
2897 if (strikethrough_set) {
2898 fmt.strikethrough = strikethrough;
2899 fmt.cs.strikethrough = TRUE;
2904 ? TEXT_POSITION_NORMAL
2905 : ( ( position == 1 )
2906 ? TEXT_POSITION_SUPERSCRIPT
2907 : TEXT_POSITION_SUBSCRIPT );
2908 fmt.cs.text_position = TRUE;
2909 fmt.font_size = oldfmt.font_size;
2913 fmt.cs.color = TRUE;
2916 fmt.font = wp_get_font_index(font_name,
2921 if (font_size_set) {
2922 fmt.cs.font_size = TRUE;
2923 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2925 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2926 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2928 gtk_widget_destroy (dialog);
2930 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2934 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2936 ModestMsgEditWindowPrivate *priv;
2938 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2939 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2941 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2943 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2944 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2948 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2950 ModestMsgEditWindowPrivate *priv;
2952 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2953 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2955 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2957 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2958 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2963 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2965 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2967 priv->can_undo = can_undo;
2971 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2973 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2975 priv->can_redo = can_redo;
2979 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2981 ModestMsgEditWindowPrivate *priv;
2982 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2983 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2985 return priv->can_undo;
2989 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2991 ModestMsgEditWindowPrivate *priv;
2992 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2993 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2995 return priv->can_redo;
3000 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3003 GtkTextIter match_start, match_end;
3005 if (image_id == NULL)
3008 gtk_text_buffer_get_start_iter (buffer, &iter);
3010 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3011 GSList *tags = gtk_text_iter_get_tags (&match_start);
3013 for (node = tags; node != NULL; node = g_slist_next (node)) {
3014 GtkTextTag *tag = (GtkTextTag *) node->data;
3015 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3016 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3017 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3019 offset = gtk_text_iter_get_offset (&match_start);
3020 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3021 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3025 gtk_text_iter_forward_char (&iter);
3030 message_is_empty (ModestMsgEditWindow *window)
3032 ModestMsgEditWindowPrivate *priv = NULL;
3034 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3035 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3037 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3038 * so we can ignore markup.
3040 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3043 count = gtk_text_buffer_get_char_count (buf);
3049 msg_body_focus (GtkWidget *focus,
3050 GdkEventFocus *event,
3054 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3055 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3056 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3061 recpt_field_changed (GtkTextBuffer *buffer,
3062 ModestMsgEditWindow *editor)
3064 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3065 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3069 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3071 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3072 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3076 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3079 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3080 GtkTextBuffer *buffer;
3082 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3083 gtk_text_buffer_set_modified (buffer, modified);
3084 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3085 gtk_text_buffer_set_modified (buffer, modified);
3086 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3087 gtk_text_buffer_set_modified (buffer, modified);
3088 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3092 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3094 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3095 const char *account_name;
3096 GtkTextBuffer *buffer;
3098 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3099 if (gtk_text_buffer_get_modified (buffer))
3101 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3102 if (gtk_text_buffer_get_modified (buffer))
3104 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3105 if (gtk_text_buffer_get_modified (buffer))
3107 if (gtk_text_buffer_get_modified (priv->text_buffer))
3109 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3110 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3121 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3123 ModestMsgEditWindowPrivate *priv = NULL;
3125 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3126 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3128 /* check if there's no recipient added */
3129 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3130 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3131 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3132 /* no recipient contents, then select contacts */
3133 modest_msg_edit_window_open_addressbook (window, NULL);
3137 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3138 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3141 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3142 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3145 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3146 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3150 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3151 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3152 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3159 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3160 ModestMsgEditWindow *window)
3162 modest_msg_edit_window_offer_attach_file (window);
3166 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3168 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3170 return priv->clipboard_text;
3174 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3176 ModestMsgEditWindow *window)
3178 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3179 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3181 if (!GTK_WIDGET_VISIBLE (window))
3184 g_object_ref (window);
3185 text = gtk_clipboard_wait_for_text (selection_clipboard);
3187 if (priv->clipboard_text != NULL) {
3188 g_free (priv->clipboard_text);
3190 priv->clipboard_text = text;
3192 if (GTK_WIDGET_VISIBLE (window)) {
3193 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3195 g_object_unref (window);
3198 static gboolean clipboard_owner_change_idle (gpointer userdata)
3200 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3201 ModestMsgEditWindowPrivate *priv;
3203 gdk_threads_enter ();
3204 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3205 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3207 priv->clipboard_owner_idle = 0;
3208 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3209 gdk_threads_leave ();
3215 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3217 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3218 if (priv->clipboard_owner_idle == 0) {
3219 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3224 subject_field_move_cursor (GtkEntry *entry,
3225 GtkMovementStep step,
3230 if (!GTK_WIDGET_VISIBLE (window))
3233 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3237 update_window_title (ModestMsgEditWindow *window)
3239 ModestMsgEditWindowPrivate *priv = NULL;
3240 const gchar *subject;
3242 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3243 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3244 if (subject == NULL || subject[0] == '\0')
3245 subject = _("mail_va_new_email");
3247 gtk_window_set_title (GTK_WINDOW (window), subject);
3252 subject_field_changed (GtkEditable *editable,
3253 ModestMsgEditWindow *window)
3255 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3256 update_window_title (window);
3257 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3258 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3259 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3263 subject_field_insert_text (GtkEditable *editable,
3265 gint new_text_length,
3267 ModestMsgEditWindow *window)
3269 GString *result = g_string_new ("");
3271 gint result_len = 0;
3272 const gchar *entry_text = NULL;
3275 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3276 old_length = g_utf8_strlen (entry_text, -1);
3278 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3279 gunichar c = g_utf8_get_char_validated (current, 8);
3280 /* Invalid unichar, stop */
3286 result = g_string_append_unichar (result, c);
3290 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3291 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3294 /* Prevent endless recursion */
3295 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3296 g_signal_emit_by_name (editable, "insert-text",
3297 (gpointer) result->str, (gpointer) result->len,
3298 (gpointer) position, (gpointer) window);
3299 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3303 if (result_len + old_length > 1000) {
3304 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3305 dgettext("hildon-common-strings",
3306 "ckdg_ib_maximum_characters_reached"));
3309 g_string_free (result, TRUE);
3313 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3316 ModestMsgEditWindowPrivate *priv = NULL;
3318 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3319 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3321 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3324 gtk_widget_show_all (priv->find_toolbar);
3325 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3327 gtk_widget_hide_all (priv->find_toolbar);
3328 gtk_widget_grab_focus (priv->msg_body);
3334 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3336 GtkTextIter *match_start,
3337 GtkTextIter *match_end)
3339 GtkTextIter end_iter;
3340 gchar *str_casefold;
3343 gchar *range_casefold;
3346 gboolean result = FALSE;
3353 gtk_text_iter_forward_to_end (&end_iter);
3355 str_casefold = g_utf8_casefold (str, -1);
3356 str_chars_n = strlen (str);
3358 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3359 range_casefold = g_utf8_casefold (range_text, -1);
3360 range_chars_n = strlen (range_casefold);
3362 if (range_chars_n < str_chars_n) {
3363 g_free (str_casefold);
3364 g_free (range_text);
3365 g_free (range_casefold);
3369 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3370 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3371 if (!g_utf8_collate (range_subtext, str_casefold)) {
3372 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3374 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3375 match_start, match_end, NULL);
3376 g_free (found_text);
3378 g_free (range_subtext);
3382 g_free (str_casefold);
3383 g_free (range_text);
3384 g_free (range_casefold);
3391 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3392 ModestMsgEditWindow *window)
3394 gchar *current_search = NULL;
3395 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3397 GtkTextIter selection_start, selection_end;
3398 GtkTextIter match_start, match_end;
3399 gboolean continue_search = FALSE;
3401 if (message_is_empty (window)) {
3402 g_free (priv->last_search);
3403 priv->last_search = NULL;
3404 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3408 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3409 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3410 g_free (current_search);
3411 g_free (priv->last_search);
3412 priv->last_search = NULL;
3413 /* Information banner about empty search */
3414 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3418 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3419 continue_search = TRUE;
3421 g_free (priv->last_search);
3422 priv->last_search = g_strdup (current_search);
3425 if (continue_search) {
3426 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3427 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3428 &match_start, &match_end);
3430 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3432 GtkTextIter buffer_start;
3433 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3434 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3435 &match_start, &match_end);
3437 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3440 /* Mark as selected the string found in search */
3442 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3443 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3444 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3446 g_free (priv->last_search);
3447 priv->last_search = NULL;
3449 g_free (current_search);
3453 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3454 ModestMsgEditWindow *window)
3456 GtkToggleAction *toggle;
3457 ModestWindowPrivate *parent_priv;
3458 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3460 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3461 gtk_toggle_action_set_active (toggle, FALSE);
3465 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3467 ModestMsgEditWindowPrivate *priv;
3469 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3474 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3477 ModestMsgEditWindowPrivate *priv;
3479 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3485 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3488 ModestMsgEditWindowPrivate *priv;
3489 TnyHeader *header = NULL;
3491 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3492 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3494 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3495 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3497 if (priv->draft_msg != NULL) {
3498 g_object_unref (priv->draft_msg);
3501 if (draft != NULL) {
3502 g_object_ref (draft);
3503 header = tny_msg_get_header (draft);
3504 if (priv->msg_uid) {
3505 g_free (priv->msg_uid);
3506 priv->msg_uid = NULL;
3508 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3509 if (GTK_WIDGET_REALIZED (window)) {
3510 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3511 gtk_widget_destroy (GTK_WIDGET (window));
3517 priv->draft_msg = draft;
3521 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3522 GtkTextIter *start, GtkTextIter *end,
3525 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3526 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3529 if (tag == NULL) return;
3530 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3531 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3532 replace_with_images (window, priv->images);
3537 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3540 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3542 g_return_if_fail (TNY_IS_MIME_PART (part));
3543 tny_list_prepend (priv->attachments, (GObject *) part);
3544 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3545 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3546 gtk_widget_show_all (priv->attachments_caption);
3547 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3551 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3553 ModestMsgEditWindowPrivate *priv;
3555 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3556 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3558 return priv->msg_uid;
3562 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3563 ModestMsgEditWindowWidgetType widget_type)
3565 ModestMsgEditWindowPrivate *priv;
3567 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3568 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3570 switch (widget_type) {
3571 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3572 return priv->msg_body;
3574 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3575 return priv->to_field;
3577 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3578 return priv->cc_field;
3580 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3581 return priv->bcc_field;
3583 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3584 return priv->subject_field;
3586 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3587 return priv->attachments_view;
3595 remove_tags (WPTextBuffer *buffer)
3597 GtkTextIter start, end;
3599 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3600 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3602 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3606 on_account_removed (TnyAccountStore *account_store,
3607 TnyAccount *account,
3610 /* Do nothing if it's a store account, because we use the
3611 transport to send the messages */
3612 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3613 const gchar *parent_acc = NULL;
3614 const gchar *our_acc = NULL;
3616 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3617 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3618 /* Close this window if I'm showing a message of the removed account */
3619 if (strcmp (parent_acc, our_acc) == 0)
3620 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3625 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3627 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3629 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3635 set_zoom_do_nothing (ModestWindow *window,
3641 get_zoom_do_nothing (ModestWindow *window)
3646 typedef struct _MessageSettingsHelper {
3647 ModestMsgEditWindow *window;
3648 GSList *priority_group;
3649 GtkWidget *align_picker;
3650 } MessageSettingsHelper;
3653 on_priority_toggle (HildonCheckButton *button,
3654 MessageSettingsHelper *helper)
3657 ModestMsgEditWindowPrivate *priv;
3659 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3660 if (hildon_check_button_get_active (button)) {
3662 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3663 HildonCheckButton *node_button = (HildonCheckButton *) node->data;
3664 if ((node_button != button) &&
3665 hildon_check_button_get_active (node_button)) {
3666 hildon_check_button_set_active (node_button, FALSE);
3668 if (priv->priority_flags != (TnyHeaderFlags) g_object_get_data (G_OBJECT (button), "priority"))
3669 modest_msg_edit_window_set_priority_flags (helper->window,
3671 g_object_get_data (G_OBJECT (button),
3677 gboolean found = FALSE;
3678 /* If no one is active, activate it again */
3679 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3680 HildonCheckButton *node_button = (HildonCheckButton *) node->data;
3681 if (hildon_check_button_get_active (node_button)) {
3687 hildon_check_button_set_active (button, TRUE);
3693 on_format_picker_value_changed (HildonPickerButton *button,
3694 MessageSettingsHelper *helper)
3696 ModestMsgEditFormat new_format, old_format;
3699 switch (hildon_picker_button_get_active (button)) {
3701 new_format = MODEST_MSG_EDIT_FORMAT_HTML;
3702 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
3706 new_format = MODEST_MSG_EDIT_FORMAT_TEXT;
3707 file_format = MODEST_FILE_FORMAT_PLAIN_TEXT;
3711 old_format = modest_msg_edit_window_get_format (helper->window);
3712 if (new_format != old_format) {
3713 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (helper->window), file_format);
3715 switch (modest_msg_edit_window_get_format (helper->window)) {
3716 case MODEST_MSG_EDIT_FORMAT_TEXT:
3717 hildon_picker_button_set_active (button, 0);
3718 gtk_widget_set_sensitive (helper->align_picker, FALSE);
3720 case MODEST_MSG_EDIT_FORMAT_HTML:
3722 hildon_picker_button_set_active (button, 1);
3723 gtk_widget_set_sensitive (helper->align_picker, TRUE);
3730 on_align_picker_value_changed (HildonPickerButton *button,
3731 MessageSettingsHelper *helper)
3733 GtkJustification new_justify;
3734 ModestMsgEditFormatState *format_state = NULL;
3736 switch (hildon_picker_button_get_active (button)) {
3738 new_justify = GTK_JUSTIFY_CENTER;
3741 new_justify = GTK_JUSTIFY_RIGHT;
3745 new_justify = GTK_JUSTIFY_LEFT;
3749 format_state = modest_msg_edit_window_get_format_state (helper->window);
3750 if (format_state->justification != new_justify)
3751 format_state->justification = new_justify;
3752 modest_msg_edit_window_set_format_state (helper->window, format_state);
3753 g_free (format_state);
3757 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3761 GtkWidget *priority_hbox;
3762 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3763 GtkWidget *captioned;
3764 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3765 GtkWidget *format_picker;
3766 GtkWidget *format_selector;
3767 GtkWidget *align_selector;
3768 ModestMsgEditWindowPrivate *priv;
3769 MessageSettingsHelper helper = {0,};
3770 ModestMsgEditFormatState *format_state = NULL;
3772 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3773 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3774 helper.window = window;
3775 helper.priority_group = NULL;
3777 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3778 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3780 dialog = gtk_dialog_new ();
3781 vbox = gtk_vbox_new (FALSE, 0);
3782 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3783 gtk_widget_show (vbox);
3785 /* Priority toggles */
3786 priority_hbox = gtk_hbox_new (TRUE, 0);
3787 high_toggle = hildon_check_button_new (HILDON_SIZE_FINGER_HEIGHT);
3788 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3789 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3790 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3791 medium_toggle = hildon_check_button_new (HILDON_SIZE_FINGER_HEIGHT);
3792 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3793 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3794 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3795 low_toggle = hildon_check_button_new (HILDON_SIZE_FINGER_HEIGHT);
3796 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3797 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3798 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3799 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, FALSE, FALSE, 0);
3800 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, FALSE, FALSE, 0);
3801 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, FALSE, FALSE, 0);
3802 gtk_widget_show_all (priority_hbox);
3803 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3804 _("mcen_me_editor_message_priority"), priority_hbox);
3805 gtk_widget_show (captioned);
3806 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3808 /* format selector */
3809 format_selector = hildon_touch_selector_new_text ();
3810 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (format_selector), _("mcen_me_editor_plain_text"));
3811 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (format_selector), _("mcen_me_editor_formatted_text"));
3812 format_picker = hildon_picker_button_new (MODEST_EDITABLE_SIZE,
3813 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
3814 hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (format_picker), HILDON_TOUCH_SELECTOR (format_selector));
3815 modest_maemo_utils_set_hbutton_layout (title_sizegroup, value_sizegroup,
3816 _("mcen_me_editor_format"), format_picker);
3817 gtk_widget_show_all (format_picker);
3818 gtk_box_pack_start (GTK_BOX (vbox), format_picker, FALSE, FALSE, 0);
3820 /* alignment selector */
3821 align_selector = hildon_touch_selector_new_text ();
3822 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (align_selector), _("mcen_me_editor_align_left"));
3823 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (align_selector), _("mcen_me_editor_align_centred"));
3824 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (align_selector), _("mcen_me_editor_align_right"));
3825 helper.align_picker = hildon_picker_button_new (MODEST_EDITABLE_SIZE,
3826 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
3827 hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (helper.align_picker), HILDON_TOUCH_SELECTOR (align_selector));
3828 modest_maemo_utils_set_hbutton_layout (title_sizegroup, value_sizegroup,
3829 _("mcen_me_editor_align"), helper.align_picker);
3830 gtk_widget_show_all (helper.align_picker);
3831 gtk_box_pack_start (GTK_BOX (vbox), helper.align_picker, FALSE, FALSE, 0);
3833 g_object_unref (title_sizegroup);
3834 g_object_unref (value_sizegroup);
3835 gtk_window_set_title (GTK_WINDOW (dialog), _("TODO: Message settings"));
3837 /* Set current values */
3838 switch (priv->priority_flags) {
3839 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3840 hildon_check_button_set_active (HILDON_CHECK_BUTTON (high_toggle), TRUE);
3842 case TNY_HEADER_FLAG_LOW_PRIORITY:
3843 hildon_check_button_set_active (HILDON_CHECK_BUTTON (low_toggle), TRUE);
3846 hildon_check_button_set_active (HILDON_CHECK_BUTTON (medium_toggle), TRUE);
3850 switch (modest_msg_edit_window_get_format (window)) {
3851 case MODEST_MSG_EDIT_FORMAT_TEXT:
3852 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (format_picker), 0);
3853 gtk_widget_set_sensitive (helper.align_picker, FALSE);
3855 case MODEST_MSG_EDIT_FORMAT_HTML:
3857 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (format_picker), 1);
3858 gtk_widget_set_sensitive (helper.align_picker, TRUE);
3862 format_state = modest_msg_edit_window_get_format_state (window);
3863 switch (format_state->justification) {
3864 case GTK_JUSTIFY_RIGHT:
3865 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 2);
3867 case GTK_JUSTIFY_CENTER:
3868 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 1);
3871 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 0);
3875 g_free (format_state);
3877 /* Signal connects */
3878 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3879 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3880 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3881 g_signal_connect (G_OBJECT (format_picker), "value-changed", G_CALLBACK (on_format_picker_value_changed), &helper);
3882 g_signal_connect (G_OBJECT (helper.align_picker), "value-changed",
3883 G_CALLBACK (on_align_picker_value_changed), &helper);
3885 gtk_dialog_run (GTK_DIALOG (dialog));
3887 /* Read new values */
3889 gtk_widget_destroy (dialog);
3890 g_slist_free (helper.priority_group);
3894 static void on_message_settings (GtkAction *action,
3895 ModestMsgEditWindow *window)
3897 modest_msg_edit_window_show_msg_settings_dialog (window);
3900 static void add_to_menu (ModestMsgEditWindow *self,
3901 HildonAppMenu *menu,
3904 ModestDimmingRulesGroup *group,
3905 GCallback dimming_callback)
3909 button = gtk_button_new_with_label (label);
3910 g_signal_connect_after (G_OBJECT (button), "clicked",
3911 callback, (gpointer) self);
3912 if (dimming_callback)
3913 modest_dimming_rules_group_add_widget_rule (group,
3916 MODEST_WINDOW (self));
3917 hildon_app_menu_append (menu, GTK_BUTTON (button));
3921 setup_menu (ModestMsgEditWindow *self, ModestDimmingRulesGroup *group)
3923 ModestMsgEditWindowPrivate *priv = NULL;
3925 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3927 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3929 priv->app_menu = hildon_app_menu_new ();
3931 /* Settings menu buttons */
3932 add_to_menu (self, HILDON_APP_MENU (priv->app_menu), _("mcen_me_editor_checknames"),
3933 G_CALLBACK (modest_ui_actions_on_check_names),
3935 add_to_menu (self, HILDON_APP_MENU (priv->app_menu), _("mcen_me_inbox_undo"),
3936 G_CALLBACK (modest_ui_actions_on_undo),
3939 /* TODO: Show/Hide CC/BCC check buttons */
3941 add_to_menu (self, HILDON_APP_MENU (priv->app_menu), _("mcen_me_editor_attach_inlineimage"),
3942 G_CALLBACK (modest_ui_actions_on_insert_image),
3944 add_to_menu (self, HILDON_APP_MENU (priv->app_menu), _("mcen_me_inbox_remove_attachments"),
3945 G_CALLBACK (modest_ui_actions_on_remove_attachments),
3947 add_to_menu (self, HILDON_APP_MENU (priv->app_menu), _("TODO: Message settings..."),
3948 G_CALLBACK (on_message_settings),
3951 /* TODO: find in toolbar check button */
3953 hildon_stackable_window_set_main_menu (HILDON_STACKABLE_WINDOW (self),
3954 HILDON_APP_MENU (priv->app_menu));
3958 modest_msg_edit_window_toggle_menu (HildonWindow *window,
3962 ModestMsgEditWindowPrivate *priv = NULL;
3964 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3966 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3968 gtk_widget_queue_resize (priv->app_menu);
3970 return HILDON_WINDOW_CLASS (parent_class)->toggle_menu (window, button, time);