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;
309 GtkWidget *cc_button;
310 GtkWidget *bcc_button;
313 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
314 MODEST_TYPE_MSG_EDIT_WINDOW, \
315 ModestMsgEditWindowPrivate))
317 static GtkWindowClass *parent_class = NULL;
319 /* uncomment the following if you have defined any signals */
320 /* static guint signals[LAST_SIGNAL] = {0}; */
323 modest_msg_edit_window_get_type (void)
325 static GType my_type = 0;
327 static const GTypeInfo my_info = {
328 sizeof(ModestMsgEditWindowClass),
329 NULL, /* base init */
330 NULL, /* base finalize */
331 (GClassInitFunc) modest_msg_edit_window_class_init,
332 NULL, /* class finalize */
333 NULL, /* class data */
334 sizeof(ModestMsgEditWindow),
336 (GInstanceInitFunc) modest_msg_edit_window_init,
339 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
340 "ModestMsgEditWindow",
348 save_state (ModestWindow *self)
350 modest_widget_memory_save (modest_runtime_get_conf(),
351 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
356 restore_settings (ModestMsgEditWindow *self)
358 ModestConf *conf = NULL;
360 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
362 conf = modest_runtime_get_conf ();
364 /* Dim at start clipboard actions */
365 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
366 gtk_action_set_sensitive (action, FALSE);
367 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
368 gtk_action_set_sensitive (action, FALSE);
369 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
370 gtk_action_set_sensitive (action, FALSE);
372 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
377 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
379 GObjectClass *gobject_class;
380 ModestWindowClass *modest_window_class;
381 HildonWindowClass *hildon_window_class = (HildonWindowClass *) klass;
382 gobject_class = (GObjectClass*) klass;
383 modest_window_class = (ModestWindowClass*) klass;
385 parent_class = g_type_class_peek_parent (klass);
386 gobject_class->finalize = modest_msg_edit_window_finalize;
388 hildon_window_class->toggle_menu = modest_msg_edit_window_toggle_menu;
390 modest_window_class->set_zoom_func = set_zoom_do_nothing;
391 modest_window_class->get_zoom_func = get_zoom_do_nothing;
392 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
393 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
394 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
395 modest_window_class->save_state_func = save_state;
396 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
398 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
402 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
404 ModestMsgEditWindowPrivate *priv;
405 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
407 priv->msg_body = NULL;
409 priv->from_field = NULL;
410 priv->to_field = NULL;
411 priv->cc_field = NULL;
412 priv->bcc_field = NULL;
413 priv->subject_field = NULL;
414 priv->attachments = TNY_LIST (tny_simple_list_new ());
415 priv->images = TNY_LIST (tny_simple_list_new ());
416 priv->images_size = 0;
417 priv->images_count = 0;
420 priv->cc_caption = NULL;
421 priv->bcc_caption = NULL;
422 priv->update_caption_visibility = FALSE;
424 priv->priority_flags = 0;
426 priv->find_toolbar = NULL;
427 priv->last_search = NULL;
429 priv->draft_msg = NULL;
430 priv->outbox_msg = NULL;
431 priv->msg_uid = NULL;
433 priv->can_undo = FALSE;
434 priv->can_redo = FALSE;
435 priv->clipboard_change_handler_id = 0;
436 priv->default_clipboard_change_handler_id = 0;
437 priv->account_removed_handler_id = 0;
438 priv->clipboard_owner_idle = 0;
439 priv->clipboard_text = NULL;
442 priv->scroll_drag_timeout_id = 0;
443 priv->last_upper = 0.0;
445 priv->font_dialog = NULL;
446 priv->app_menu = NULL;
448 if (!is_wp_text_buffer_started) {
449 is_wp_text_buffer_started = TRUE;
450 wp_text_buffer_library_init ();
455 hildon_program_add_window (hildon_program_get_instance(),
461 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
463 static ModestPairList*
464 get_transports (void)
466 GSList *transports = NULL;
468 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
469 GSList *accounts = modest_account_mgr_account_names (account_mgr,
470 TRUE /* only enabled accounts. */);
472 GSList *cursor = accounts;
474 gchar *account_name = cursor->data;
475 gchar *from_string = NULL;
477 from_string = modest_account_mgr_get_from_string (account_mgr,
481 if (from_string && account_name) {
482 gchar *name = account_name;
483 ModestPair *pair = modest_pair_new ((gpointer) name,
484 (gpointer) from_string , TRUE);
485 transports = g_slist_prepend (transports, pair);
488 cursor = cursor->next;
490 g_slist_free (accounts); /* only free the accounts, not the elements,
491 * because they are used in the pairlist */
495 static void window_focus (GtkWindow *window,
499 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
503 scroll_drag_timeout (gpointer userdata)
505 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
506 ModestMsgEditWindowPrivate *priv;
508 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
510 correct_scroll_without_drag_check (win, TRUE);
512 priv->scroll_drag_timeout_id = 0;
518 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
520 ModestMsgEditWindowPrivate *priv;
523 GdkRectangle rectangle;
527 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
529 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
532 insert = gtk_text_buffer_get_insert (priv->text_buffer);
533 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
535 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
536 offset = priv->msg_body->allocation.y;
538 new_value = (offset + rectangle.y);
540 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (priv->pannable), -1, new_value);
544 correct_scroll (ModestMsgEditWindow *w)
546 ModestMsgEditWindowPrivate *priv;
548 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
549 if (gtk_grab_get_current () == priv->msg_body) {
550 if (priv->scroll_drag_timeout_id == 0) {
551 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
557 correct_scroll_without_drag_check (w, TRUE);
561 text_buffer_end_user_action (GtkTextBuffer *buffer,
562 ModestMsgEditWindow *userdata)
565 correct_scroll (userdata);
569 text_buffer_mark_set (GtkTextBuffer *buffer,
572 ModestMsgEditWindow *userdata)
574 gtk_text_buffer_begin_user_action (buffer);
575 gtk_text_buffer_end_user_action (buffer);
579 cut_clipboard_check (GtkTextView *text_view,
582 GtkTextBuffer *buffer;
584 buffer = gtk_text_view_get_buffer (text_view);
585 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
586 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
591 copy_clipboard_check (GtkTextView *text_view,
594 GtkTextBuffer *buffer;
596 buffer = gtk_text_view_get_buffer (text_view);
597 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
598 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
603 attachment_deleted (ModestAttachmentsView *attachments_view,
606 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
611 connect_signals (ModestMsgEditWindow *obj)
613 ModestMsgEditWindowPrivate *priv;
615 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
617 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
618 G_CALLBACK (text_buffer_refresh_attributes), obj);
619 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
620 G_CALLBACK (text_buffer_can_undo), obj);
621 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
622 G_CALLBACK (text_buffer_can_redo), obj);
623 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
624 G_CALLBACK (body_changed), obj);
625 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
626 G_CALLBACK (body_changed), obj);
627 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
628 G_CALLBACK (text_buffer_end_user_action), obj);
629 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
630 G_CALLBACK (text_buffer_mark_set), obj);
631 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
632 G_CALLBACK (text_buffer_apply_tag), obj);
633 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
634 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
635 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
636 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
637 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
638 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
640 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
641 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
643 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
644 G_CALLBACK (msg_body_focus), obj);
645 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
646 G_CALLBACK (msg_body_focus), obj);
647 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
648 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
649 "changed", G_CALLBACK (recpt_field_changed), obj);
650 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
651 "changed", G_CALLBACK (recpt_field_changed), obj);
652 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
653 "changed", G_CALLBACK (recpt_field_changed), obj);
654 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
655 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
656 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
658 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
659 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
661 priv->clipboard_change_handler_id =
662 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
663 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
664 priv->default_clipboard_change_handler_id =
665 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
666 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
668 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
669 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
670 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
674 init_wp_text_view_style ()
676 static gboolean initialized = FALSE;
679 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
685 init_window (ModestMsgEditWindow *obj)
687 GtkWidget *to_caption, *subject_caption;
688 GtkWidget *main_vbox;
689 ModestMsgEditWindowPrivate *priv;
690 GtkActionGroup *action_group;
691 ModestWindowPrivate *parent_priv;
692 GdkPixbuf *window_icon = NULL;
693 GError *error = NULL;
695 GtkSizeGroup *title_size_group;
696 GtkSizeGroup *value_size_group;
697 GtkWidget *subject_box;
698 GtkWidget *attachment_icon;
699 GtkWidget *window_box;
700 #if (GTK_MINOR_VERSION >= 10)
701 GdkAtom deserialize_type;
704 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
705 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
707 parent_priv->ui_manager = gtk_ui_manager_new();
708 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
709 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
711 /* Add common actions */
712 gtk_action_group_add_actions (action_group,
713 modest_msg_edit_action_entries,
714 G_N_ELEMENTS (modest_msg_edit_action_entries),
716 gtk_action_group_add_actions (action_group,
717 hildon2_msg_edit_action_entries,
718 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
720 gtk_action_group_add_toggle_actions (action_group,
721 modest_msg_edit_toggle_action_entries,
722 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
724 gtk_action_group_add_radio_actions (action_group,
725 modest_msg_edit_alignment_radio_action_entries,
726 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
728 G_CALLBACK (modest_ui_actions_on_change_justify),
730 gtk_action_group_add_radio_actions (action_group,
731 modest_msg_edit_priority_action_entries,
732 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
734 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
736 gtk_action_group_add_radio_actions (action_group,
737 modest_msg_edit_file_format_action_entries,
738 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
739 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
740 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
742 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
743 g_object_unref (action_group);
745 /* Load the UI definition */
746 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
749 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
750 g_clear_error (&error);
753 /* Add accelerators */
754 gtk_window_add_accel_group (GTK_WINDOW (obj),
755 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
757 parent_priv->menubar = NULL;
759 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
760 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
762 /* Note: This ModestPairList* must exist for as long as the picker
763 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
764 * so it can't know how to manage its memory. */
765 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
766 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
768 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
769 _("mail_va_from"), priv->from_field);
771 priv->to_field = modest_recpt_editor_new ();
772 priv->cc_field = modest_recpt_editor_new ();
773 priv->bcc_field = modest_recpt_editor_new ();
774 subject_box = gtk_hbox_new (FALSE, 0);
775 priv->priority_icon = gtk_image_new ();
776 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
777 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
778 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
779 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
780 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
781 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
782 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
783 priv->add_attachment_button = gtk_button_new ();
784 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
785 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
786 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
787 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 0.5);
788 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
789 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
790 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
791 priv->attachments_view = modest_attachments_view_new (NULL);
793 priv->header_box = gtk_vbox_new (FALSE, 0);
795 to_caption = modest_maemo_utils_create_captioned_with_size_type
796 (title_size_group, value_size_group,
797 _("mail_va_to"), priv->to_field,
798 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
799 priv->cc_caption = modest_maemo_utils_create_captioned_with_size_type
800 (title_size_group, value_size_group,
801 _("mail_va_cc"), priv->cc_field,
802 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
803 priv->bcc_caption = modest_maemo_utils_create_captioned_with_size_type
804 (title_size_group, value_size_group,
805 _("mail_va_hotfix1"), priv->bcc_field,
806 HILDON_SIZE_AUTO_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
807 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
808 _("mail_va_subject"), subject_box);
809 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
810 _("mail_va_attachment"),
811 priv->attachments_view,
812 HILDON_SIZE_AUTO_WIDTH |
813 HILDON_SIZE_AUTO_HEIGHT);
814 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
815 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
816 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
817 g_object_unref (title_size_group);
818 g_object_unref (value_size_group);
820 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
821 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
822 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
823 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
824 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
825 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
826 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
828 init_wp_text_view_style ();
830 priv->msg_body = wp_text_view_new ();
833 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
834 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
835 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
836 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
837 #if (GTK_MINOR_VERSION >= 10)
838 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
839 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
841 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
842 deserialize_type, TRUE);
844 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
846 priv->find_toolbar = hildon_find_toolbar_new (NULL);
847 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
849 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
851 priv->pannable = hildon_pannable_area_new ();
853 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
855 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
856 priv->frame = gtk_frame_new (NULL);
857 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
859 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), main_vbox);
860 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
862 window_box = gtk_vbox_new (FALSE, 0);
863 gtk_container_add (GTK_CONTAINER(obj), window_box);
865 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
867 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
869 /* Set window icon */
870 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
872 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
873 g_object_unref (window_icon);
878 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
880 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
882 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
883 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
884 priv->clipboard_change_handler_id))
885 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
886 priv->clipboard_change_handler_id);
887 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
888 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
889 priv->default_clipboard_change_handler_id))
890 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
891 priv->default_clipboard_change_handler_id);
893 if (priv->account_removed_handler_id &&
894 g_signal_handler_is_connected (modest_runtime_get_account_store (),
895 priv->account_removed_handler_id))
896 g_signal_handler_disconnect(modest_runtime_get_account_store (),
897 priv->account_removed_handler_id);
901 modest_msg_edit_window_finalize (GObject *obj)
903 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
905 /* Sanity check: shouldn't be needed, the window mgr should
906 call this function before */
907 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
909 if (priv->font_dialog != NULL) {
910 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
913 if (priv->clipboard_text != NULL) {
914 g_free (priv->clipboard_text);
915 priv->clipboard_text = NULL;
918 if (priv->draft_msg != NULL) {
919 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
920 if (TNY_IS_HEADER (header)) {
921 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
922 modest_window_mgr_unregister_header (mgr, header);
924 g_object_unref (priv->draft_msg);
925 priv->draft_msg = NULL;
927 if (priv->outbox_msg != NULL) {
928 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
929 if (TNY_IS_HEADER (header)) {
930 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
931 modest_window_mgr_unregister_header (mgr, header);
933 g_object_unref (priv->outbox_msg);
934 priv->outbox_msg = NULL;
936 if (priv->scroll_drag_timeout_id > 0) {
937 g_source_remove (priv->scroll_drag_timeout_id);
938 priv->scroll_drag_timeout_id = 0;
940 if (priv->clipboard_owner_idle > 0) {
941 g_source_remove (priv->clipboard_owner_idle);
942 priv->clipboard_owner_idle = 0;
944 if (priv->original_account_name)
945 g_free (priv->original_account_name);
946 g_free (priv->msg_uid);
947 g_free (priv->last_search);
948 g_slist_free (priv->font_items_group);
949 g_slist_free (priv->size_items_group);
950 g_object_unref (priv->attachments);
951 g_object_unref (priv->images);
953 /* This had to stay alive for as long as the picker that used it: */
954 modest_pair_list_free (priv->from_field_protos);
956 G_OBJECT_CLASS(parent_class)->finalize (obj);
960 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
962 GdkPixbufLoader *loader;
968 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
970 if (loader == NULL) {
976 tny_stream_reset (TNY_STREAM (stream));
977 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
978 GError *error = NULL;
979 unsigned char read_buffer[128];
981 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
983 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
985 g_error_free (error);
990 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
992 g_object_ref (pixbuf);
993 gdk_pixbuf_loader_close (loader, NULL);
994 g_object_unref (loader);
999 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1000 GdkPixbuf *new_pixbuf;
1002 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1003 gdk_pixbuf_get_width (pixbuf);
1004 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1005 g_object_unref (pixbuf);
1006 pixbuf = new_pixbuf;
1010 *stream_size = size;
1016 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1018 ModestMsgEditWindowPrivate *priv;
1021 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1023 for (iter = tny_list_create_iterator (attachments);
1024 !tny_iterator_is_done (iter);
1025 tny_iterator_next (iter)) {
1026 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1027 const gchar *cid = tny_mime_part_get_content_id (part);
1028 const gchar *mime_type = tny_mime_part_get_content_type (part);
1029 if ((cid != NULL)&&(mime_type != NULL)) {
1030 guint64 stream_size;
1031 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1032 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1035 g_object_unref (stream);
1037 if (pixbuf != NULL) {
1038 priv->images_count ++;
1039 priv->images_size += stream_size;
1040 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1041 g_object_unref (pixbuf);
1044 g_object_unref (part);
1046 g_object_unref (iter);
1050 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1052 TnyMimePart *parent = NULL;
1053 const gchar *content_type = NULL;
1054 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1056 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1058 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1059 parent = g_object_ref (msg);
1060 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1061 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1064 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1065 iter = tny_list_create_iterator (parts);
1066 while (!tny_iterator_is_done (iter)) {
1068 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1069 content_type = tny_mime_part_get_content_type (part);
1070 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1074 g_object_unref (part);
1076 tny_iterator_next (iter);
1078 g_object_unref (iter);
1079 g_object_unref (parts);
1082 if (parent != NULL) {
1083 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1086 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1087 iter = tny_list_create_iterator (parts);
1088 while (!tny_iterator_is_done (iter)) {
1090 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1091 content_type = tny_mime_part_get_content_type (part);
1092 if (content_type && g_str_has_prefix (content_type, "image/")) {
1093 tny_list_prepend (priv->images, (GObject *) part);
1095 g_object_unref (part);
1096 tny_iterator_next (iter);
1098 g_object_unref (iter);
1099 g_object_unref (parts);
1100 g_object_unref (parent);
1105 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1108 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1110 for (iter = tny_list_create_iterator (attachments) ;
1111 !tny_iterator_is_done (iter);
1112 tny_iterator_next (iter)) {
1113 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1114 const gchar *cid = tny_mime_part_get_content_id (part);
1116 char *invalid = NULL;
1117 gint int_cid = strtol (cid, &invalid, 10);
1118 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1119 priv->next_cid = int_cid + 1;
1122 g_object_unref (part);
1124 g_object_unref (iter);
1128 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1131 gchar *to, *cc, *bcc, *subject;
1133 ModestMsgEditWindowPrivate *priv;
1134 ModestWindowPrivate *parent_priv;
1136 TnyHeaderFlags priority_flags;
1137 TnyFolder *msg_folder;
1138 gboolean is_html = FALSE;
1139 gboolean field_view_set;
1141 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1142 g_return_if_fail (TNY_IS_MSG (msg));
1144 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1145 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1147 header = tny_msg_get_header (msg);
1148 to = tny_header_dup_to (header);
1149 cc = tny_header_dup_cc (header);
1150 bcc = tny_header_dup_bcc (header);
1151 subject = tny_header_dup_subject (header);
1152 priority_flags = tny_header_get_priority (header);
1155 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
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;
1167 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1169 field_view_set = TRUE;
1171 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1172 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1173 gtk_widget_show (priv->bcc_caption);
1174 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1175 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1176 gtk_widget_hide (priv->bcc_caption);
1177 field_view_set = FALSE;
1179 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1183 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1184 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1187 update_window_title (self);
1189 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1190 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1192 if ((body == NULL)||(body[0] == '\0')) {
1194 body = modest_text_utils_convert_to_html ("");
1197 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1198 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1201 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1204 /* Add attachments to the view */
1205 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1206 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1207 if (tny_list_get_length (priv->attachments) == 0) {
1208 gtk_widget_hide (priv->attachments_caption);
1210 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1211 gtk_widget_show_all (priv->attachments_caption);
1213 get_related_images (self, msg);
1214 update_next_cid (self, priv->attachments);
1215 update_next_cid (self, priv->images);
1216 replace_with_images (self, priv->images);
1218 if (preserve_is_rich && !is_html) {
1219 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1220 /* Get the default format required from configuration */
1221 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1222 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1225 /* Set the default focus depending on having already a To: field or not */
1226 if ((!to)||(*to == '\0')) {
1227 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1229 gtk_widget_grab_focus (priv->msg_body);
1232 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1234 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1235 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1237 modest_msg_edit_window_set_modified (self, FALSE);
1239 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1240 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1241 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1242 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1244 if (priv->msg_uid) {
1245 g_free (priv->msg_uid);
1246 priv->msg_uid = NULL;
1249 /* we should set a reference to the incoming message if it is a draft */
1250 msg_folder = tny_msg_get_folder (msg);
1252 if (modest_tny_folder_is_local_folder (msg_folder)) {
1253 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1254 if (type == TNY_FOLDER_TYPE_INVALID)
1255 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1257 if (type == TNY_FOLDER_TYPE_DRAFTS)
1258 priv->draft_msg = g_object_ref(msg);
1259 if (type == TNY_FOLDER_TYPE_OUTBOX)
1260 priv->outbox_msg = g_object_ref(msg);
1261 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1263 g_object_unref (msg_folder);
1273 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1276 GList *item_children, *node;
1277 GtkWidget *bin_child;
1279 bin_child = gtk_bin_get_child (GTK_BIN(item));
1281 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1283 for (node = item_children; node != NULL; node = g_list_next (node)) {
1284 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1285 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1288 g_list_free (item_children);
1292 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1295 GList *item_children, *node;
1297 box = gtk_bin_get_child (GTK_BIN (item));
1298 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1299 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1301 for (node = item_children; node != NULL; node = g_list_next (node)) {
1302 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1303 if (GTK_IS_TOGGLE_BUTTON (node->data))
1304 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1305 else if (GTK_IS_BUTTON (node->data))
1306 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1308 g_list_free (item_children);
1313 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1315 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1316 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1317 GtkWidget *placeholder;
1318 GtkWidget *tool_item;
1323 GtkWidget *sizes_menu;
1324 GtkWidget *fonts_menu;
1325 GSList *radio_group = NULL;
1326 GSList *node = NULL;
1330 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1331 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1333 /* Font color placeholder */
1334 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1335 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1338 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1339 priv->font_color_button = hildon_color_button_new ();
1340 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1341 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1342 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1343 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1344 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1345 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1346 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1348 G_CALLBACK (modest_msg_edit_window_color_button_change),
1351 /* Font size and face placeholder */
1352 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1353 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1355 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1356 priv->size_tool_button_label = gtk_label_new (NULL);
1357 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1358 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1359 size_text,"</span>", NULL);
1360 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1362 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1363 sizes_menu = gtk_menu_new ();
1364 priv->size_items_group = NULL;
1366 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1367 GtkWidget *size_menu_item;
1369 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1370 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1371 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1372 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1373 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1374 gtk_widget_show (size_menu_item);
1376 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1380 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1381 GtkWidget *item = (GtkWidget *) node->data;
1382 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1386 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1387 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1388 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1389 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1390 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1391 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1392 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1393 priv->font_size_toolitem = tool_item;
1396 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1397 priv->font_tool_button_label = gtk_label_new (NULL);
1398 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1399 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1401 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1402 fonts_menu = gtk_menu_new ();
1403 priv->font_items_group = NULL;
1405 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1406 GtkWidget *font_menu_item;
1407 GtkWidget *child_label;
1409 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1410 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1411 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1412 wp_get_font_name (font_index), "</span>", NULL);
1413 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1416 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1417 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1418 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1419 gtk_widget_show (font_menu_item);
1421 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1424 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1425 GtkWidget *item = (GtkWidget *) node->data;
1426 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1429 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1430 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1431 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1432 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1433 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1434 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1435 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1436 priv->font_face_toolitem = tool_item;
1438 /* Set expand and homogeneous for remaining items */
1439 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1440 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1441 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1442 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
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/ActionsItalics");
1446 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1447 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1449 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1450 will not show the tool items added to the placeholders) */
1451 gtk_widget_show_all (parent_priv->toolbar);
1453 /* Set the no show all *after* showing all items. We do not
1454 want the toolbar to be shown with a show all because it
1455 could go agains the gconf setting regarding showing or not
1456 the toolbar of the editor window */
1457 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1463 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1466 ModestWindowPrivate *parent_priv;
1467 ModestMsgEditWindowPrivate *priv;
1468 ModestDimmingRulesGroup *menu_rules_group = NULL;
1469 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1470 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1471 ModestWindowMgr *mgr = NULL;
1473 g_return_val_if_fail (msg, NULL);
1474 g_return_val_if_fail (account_name, NULL);
1476 mgr = modest_runtime_get_window_mgr ();
1478 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1480 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1481 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1483 /* Menubar. Update the state of some toggles */
1484 priv->from_field_protos = get_transports ();
1485 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1486 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1487 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1489 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1490 hildon_touch_selector_get_current_text
1491 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1492 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1493 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1496 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1498 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1500 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1502 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1504 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1505 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1506 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1507 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1508 /* Add common dimming rules */
1509 modest_dimming_rules_group_add_rules (menu_rules_group,
1510 modest_msg_edit_window_menu_dimming_entries,
1511 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1512 MODEST_WINDOW (obj));
1513 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1514 modest_msg_edit_window_toolbar_dimming_entries,
1515 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1516 MODEST_WINDOW (obj));
1517 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1518 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1519 MODEST_WINDOW (obj));
1520 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_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_face_toolitem,
1524 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1525 MODEST_WINDOW (obj));
1526 /* Insert dimming rules group for this window */
1527 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1528 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1529 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1531 /* Setup app menu */
1532 setup_menu (MODEST_MSG_EDIT_WINDOW (obj), menu_rules_group);
1534 /* Checks the dimming rules */
1535 g_object_unref (menu_rules_group);
1536 g_object_unref (toolbar_rules_group);
1537 g_object_unref (clipboard_rules_group);
1538 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1540 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1542 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1543 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1544 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1545 priv->update_caption_visibility = TRUE;
1547 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1549 /* Track account-removed signal, this window should be closed
1550 in the case we're creating a mail associated to the account
1552 priv->account_removed_handler_id =
1553 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1555 G_CALLBACK(on_account_removed),
1558 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1560 return (ModestWindow*) obj;
1564 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1566 GString **string_buffer = (GString **) user_data;
1568 *string_buffer = g_string_append (*string_buffer, buffer);
1574 * @result: A new string which should be freed with g_free().
1577 get_formatted_data (ModestMsgEditWindow *edit_window)
1579 ModestMsgEditWindowPrivate *priv;
1580 GString *string_buffer = g_string_new ("");
1582 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1584 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1586 modest_text_utils_hyperlinkify (string_buffer);
1588 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1590 return g_string_free (string_buffer, FALSE);
1595 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1598 const gchar *account_name;
1599 ModestMsgEditWindowPrivate *priv;
1600 TnyIterator *att_iter;
1602 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1604 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1606 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1607 g_return_val_if_fail (account_name, NULL);
1610 /* don't free these (except from) */
1611 data = g_slice_new0 (MsgData);
1612 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1614 data->account_name = g_strdup (account_name);
1615 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1616 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1617 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1618 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1619 if (priv->draft_msg) {
1620 data->draft_msg = g_object_ref (priv->draft_msg);
1621 } else if (priv->outbox_msg) {
1622 data->draft_msg = g_object_ref (priv->outbox_msg);
1624 data->draft_msg = NULL;
1627 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1629 gtk_text_buffer_get_bounds (buf, &b, &e);
1630 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1632 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1633 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1635 data->html_body = NULL;
1637 /* deep-copy the data */
1638 att_iter = tny_list_create_iterator (priv->attachments);
1639 data->attachments = NULL;
1640 while (!tny_iterator_is_done (att_iter)) {
1641 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1642 if (!(TNY_IS_MIME_PART(part))) {
1643 g_warning ("strange data in attachment list");
1644 g_object_unref (part);
1645 tny_iterator_next (att_iter);
1648 data->attachments = g_list_append (data->attachments,
1650 tny_iterator_next (att_iter);
1652 g_object_unref (att_iter);
1654 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1655 att_iter = tny_list_create_iterator (priv->images);
1656 data->images = NULL;
1657 while (!tny_iterator_is_done (att_iter)) {
1658 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1660 if (!(TNY_IS_MIME_PART(part))) {
1661 g_warning ("strange data in attachment list");
1662 g_object_unref (part);
1663 tny_iterator_next (att_iter);
1666 cid = tny_mime_part_get_content_id (part);
1668 gchar *image_tag_id;
1669 GtkTextTag *image_tag;
1671 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1672 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1673 g_free (image_tag_id);
1675 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1677 ((gtk_text_iter_has_tag (&iter, image_tag))||
1678 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1679 data->images = g_list_append (data->images,
1680 g_object_ref (part));
1682 g_object_unref (part);
1683 tny_iterator_next (att_iter);
1685 g_object_unref (att_iter);
1687 data->priority_flags = priv->priority_flags;
1694 unref_gobject (GObject *obj, gpointer data)
1696 if (!G_IS_OBJECT(obj))
1698 g_object_unref (obj);
1702 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1705 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1713 g_free (data->from);
1714 g_free (data->subject);
1715 g_free (data->plain_body);
1716 g_free (data->html_body);
1717 g_free (data->account_name);
1719 if (data->draft_msg != NULL) {
1720 g_object_unref (data->draft_msg);
1721 data->draft_msg = NULL;
1724 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1725 g_list_free (data->attachments);
1726 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1727 g_list_free (data->images);
1729 g_slice_free (MsgData, data);
1733 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1735 guint64 *parts_size)
1737 ModestMsgEditWindowPrivate *priv;
1739 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1741 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1743 /* TODO: add images */
1744 *parts_size += priv->images_size;
1745 *parts_count += priv->images_count;
1750 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1753 ModestMsgEditWindowPrivate *priv = NULL;
1754 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1756 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1758 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1760 return MODEST_MSG_EDIT_FORMAT_HTML;
1762 return MODEST_MSG_EDIT_FORMAT_TEXT;
1766 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1767 ModestMsgEditFormat format)
1769 ModestMsgEditWindowPrivate *priv;
1771 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1772 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1775 case MODEST_MSG_EDIT_FORMAT_HTML:
1776 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1778 case MODEST_MSG_EDIT_FORMAT_TEXT:
1779 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1782 g_return_if_reached ();
1786 ModestMsgEditFormatState *
1787 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1789 ModestMsgEditFormatState *format_state = NULL;
1790 ModestMsgEditWindowPrivate *priv;
1791 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1793 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1794 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1796 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1798 format_state = g_new0 (ModestMsgEditFormatState, 1);
1799 format_state->bold = buffer_format->bold&0x1;
1800 format_state->italics = buffer_format->italic&0x1;
1801 format_state->bullet = buffer_format->bullet&0x1;
1802 format_state->color = buffer_format->color;
1803 format_state->font_size = buffer_format->font_size;
1804 format_state->font_family = wp_get_font_name (buffer_format->font);
1805 format_state->justification = buffer_format->justification;
1806 g_free (buffer_format);
1808 return format_state;
1813 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1814 const ModestMsgEditFormatState *format_state)
1816 ModestMsgEditWindowPrivate *priv;
1817 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1818 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1819 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1820 g_return_if_fail (format_state != NULL);
1822 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1823 gtk_widget_grab_focus (priv->msg_body);
1824 buffer_format->bold = (format_state->bold != FALSE);
1825 buffer_format->italic = (format_state->italics != FALSE);
1826 buffer_format->color = format_state->color;
1827 buffer_format->font_size = format_state->font_size;
1828 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1829 buffer_format->justification = format_state->justification;
1830 buffer_format->bullet = format_state->bullet;
1832 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1834 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1835 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1836 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1837 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1838 buffer_format->cs.font = (buffer_format->font != current_format->font);
1839 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1840 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1842 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1843 if (buffer_format->cs.bold) {
1844 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1845 GINT_TO_POINTER (buffer_format->bold&0x1));
1847 if (buffer_format->cs.italic) {
1848 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1849 GINT_TO_POINTER (buffer_format->italic&0x1));
1851 if (buffer_format->cs.color) {
1852 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1853 GINT_TO_POINTER (&(buffer_format->color)));
1855 if (buffer_format->cs.font_size) {
1856 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1857 GINT_TO_POINTER (buffer_format->font_size));
1859 if (buffer_format->cs.justification) {
1860 switch (buffer_format->justification) {
1861 case GTK_JUSTIFY_LEFT:
1862 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1863 GINT_TO_POINTER(TRUE));
1865 case GTK_JUSTIFY_CENTER:
1866 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1867 GINT_TO_POINTER(TRUE));
1869 case GTK_JUSTIFY_RIGHT:
1870 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1871 GINT_TO_POINTER(TRUE));
1878 if (buffer_format->cs.font) {
1879 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1880 GINT_TO_POINTER (buffer_format->font));
1882 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1883 if (buffer_format->cs.bullet) {
1884 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1885 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1887 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1889 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1891 g_free (buffer_format);
1892 g_free (current_format);
1894 /* Check dimming rules */
1895 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1896 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1900 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1902 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1904 ModestWindowPrivate *parent_priv;
1905 ModestMsgEditWindowPrivate *priv;
1906 GtkWidget *new_size_menuitem;
1907 GtkWidget *new_font_menuitem;
1909 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1910 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1912 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1913 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1914 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1915 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1917 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1918 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1919 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1922 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1924 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1925 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1927 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1928 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1930 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1931 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1934 switch (buffer_format->justification)
1936 case GTK_JUSTIFY_LEFT:
1937 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1939 case GTK_JUSTIFY_CENTER:
1940 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1942 case GTK_JUSTIFY_RIGHT:
1943 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1950 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1952 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1953 G_CALLBACK (modest_msg_edit_window_color_button_change),
1955 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1956 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1957 G_CALLBACK (modest_msg_edit_window_color_button_change),
1960 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1961 buffer_format->font_size))->data);
1962 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1966 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1967 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1968 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1970 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1971 G_CALLBACK (modest_msg_edit_window_size_change),
1973 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1974 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1975 G_CALLBACK (modest_msg_edit_window_size_change),
1979 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1980 buffer_format->font))->data);
1981 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1985 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1986 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1987 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1989 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1990 G_CALLBACK (modest_msg_edit_window_font_change),
1992 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1993 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1994 G_CALLBACK (modest_msg_edit_window_font_change),
1998 g_free (buffer_format);
2002 #ifdef MODEST_HILDON_VERSION_0
2004 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2007 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2008 ModestMsgEditWindowPrivate *priv;
2009 GtkWidget *dialog = NULL;
2011 GdkColor *new_color = NULL;
2013 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2014 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2016 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2017 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2018 g_free (buffer_format);
2020 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2021 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2022 if (new_color != NULL) {
2023 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2024 (gpointer) new_color);
2027 gtk_widget_destroy (dialog);
2032 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2035 ModestMsgEditWindowPrivate *priv;
2036 GtkWidget *dialog = NULL;
2038 GdkColor *old_color = NULL;
2039 const GdkColor *new_color = NULL;
2041 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2042 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2044 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2045 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2047 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2048 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2049 if (new_color != NULL)
2050 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2052 gtk_widget_destroy (dialog);
2058 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2061 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2062 ModestMsgEditWindowPrivate *priv;
2063 GtkWidget *dialog = NULL;
2065 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2066 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2068 dialog = hildon_color_chooser_new ();
2069 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2070 g_free (buffer_format);
2072 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2074 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2075 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2078 gtk_widget_destroy (dialog);
2083 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2086 ModestMsgEditWindowPrivate *priv;
2087 GtkWidget *dialog = NULL;
2088 GdkColor *old_color = NULL;
2090 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2091 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2093 dialog = hildon_color_chooser_new ();
2094 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2096 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2098 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2099 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2101 gtk_widget_destroy (dialog);
2104 #endif /*!MODEST_HILDON_VERSION_0*/
2109 create_stream_for_uri (const gchar* uri)
2114 TnyStream *result = NULL;
2116 GnomeVFSHandle *handle = NULL;
2117 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2118 if (test == GNOME_VFS_OK) {
2119 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2120 /* Streams over OBEX (Bluetooth) are not seekable but
2121 * we expect them to be (we might need to read them
2122 * several times). So if this is a Bluetooth URI just
2123 * read the whole file into memory (this is not a fast
2124 * protocol so we can assume that these files are not
2125 * going to be very big) */
2126 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2127 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2128 TnyStream *memstream = tny_camel_mem_stream_new ();
2129 tny_stream_write_to_stream (vfssstream, memstream);
2130 g_object_unref (vfssstream);
2133 result = vfssstream;
2141 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2144 ModestMsgEditWindowPrivate *priv;
2145 GtkWidget *dialog = NULL;
2147 GSList *uris = NULL;
2148 GSList *uri_node = NULL;
2150 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2152 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2153 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2154 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2156 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2158 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2159 GTK_WINDOW (dialog), GTK_WINDOW (window));
2161 response = gtk_dialog_run (GTK_DIALOG (dialog));
2163 case GTK_RESPONSE_OK:
2164 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2169 gtk_widget_destroy (dialog);
2171 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2173 GnomeVFSHandle *handle = NULL;
2174 GnomeVFSResult result;
2175 GtkTextIter position;
2176 GtkTextMark *insert_mark;
2178 uri = (const gchar *) uri_node->data;
2179 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2180 if (result == GNOME_VFS_OK) {
2182 GnomeVFSFileInfo *info;
2183 gchar *filename, *basename, *escaped_filename;
2184 TnyMimePart *mime_part;
2186 const gchar *mime_type = NULL;
2187 GnomeVFSURI *vfs_uri;
2188 guint64 stream_size;
2190 gnome_vfs_close (handle);
2191 vfs_uri = gnome_vfs_uri_new (uri);
2193 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2194 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2195 g_free (escaped_filename);
2196 gnome_vfs_uri_unref (vfs_uri);
2197 info = gnome_vfs_file_info_new ();
2199 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2200 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2202 mime_type = gnome_vfs_file_info_get_mime_type (info);
2204 mime_part = tny_platform_factory_new_mime_part
2205 (modest_runtime_get_platform_factory ());
2207 TnyStream *stream = create_stream_for_uri (uri);
2209 if (stream == NULL) {
2211 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2213 g_object_unref (mime_part);
2214 gnome_vfs_file_info_unref (info);
2218 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2220 content_id = g_strdup_printf ("%d", priv->next_cid);
2221 tny_mime_part_set_content_id (mime_part, content_id);
2222 g_free (content_id);
2225 basename = g_path_get_basename (filename);
2226 tny_mime_part_set_filename (mime_part, basename);
2229 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2231 if (pixbuf != NULL) {
2232 priv->images_size += stream_size;
2233 priv->images_count ++;
2234 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2235 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2236 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2237 g_object_unref (pixbuf);
2240 tny_list_prepend (priv->images, (GObject *) mime_part);
2241 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2243 g_object_unref (mime_part);
2244 gnome_vfs_file_info_unref (info);
2253 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2255 GtkWidget *dialog = NULL;
2257 GSList *uris = NULL;
2259 GnomeVFSFileSize total_size, allowed_size;
2260 ModestMsgEditWindowPrivate *priv;
2264 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2266 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2268 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2271 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2272 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2273 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2274 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), GTK_WINDOW (window));
2276 response = gtk_dialog_run (GTK_DIALOG (dialog));
2278 case GTK_RESPONSE_OK:
2279 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2284 gtk_widget_destroy (dialog);
2286 /* allowed size is the maximum size - what's already there */
2287 modest_attachments_view_get_sizes (
2288 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2289 &att_num, &att_size);
2290 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2293 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2295 const gchar *uri = (const gchar *) uri_node->data;
2297 total_size += modest_msg_edit_window_attach_file_one
2298 (window, uri, allowed_size);
2300 if (total_size > allowed_size) {
2301 g_warning ("%s: total size: %u",
2302 __FUNCTION__, (unsigned int)total_size);
2306 allowed_size -= total_size;
2310 g_slist_foreach (uris, (GFunc) g_free, NULL);
2311 g_slist_free (uris);
2316 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2318 GnomeVFSFileSize allowed_size)
2321 GnomeVFSHandle *handle = NULL;
2322 ModestMsgEditWindowPrivate *priv;
2323 GnomeVFSResult result;
2324 GnomeVFSFileSize size = 0;
2325 g_return_val_if_fail (window, 0);
2326 g_return_val_if_fail (uri, 0);
2328 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2330 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2331 if (result == GNOME_VFS_OK) {
2332 TnyMimePart *mime_part;
2334 const gchar *mime_type = NULL;
2336 gchar *escaped_filename;
2339 GnomeVFSFileInfo *info;
2340 GnomeVFSURI *vfs_uri;
2342 gnome_vfs_close (handle);
2343 vfs_uri = gnome_vfs_uri_new (uri);
2346 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2347 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2348 g_free (escaped_filename);
2349 gnome_vfs_uri_unref (vfs_uri);
2351 info = gnome_vfs_file_info_new ();
2353 if (gnome_vfs_get_file_info (uri,
2355 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2357 mime_type = gnome_vfs_file_info_get_mime_type (info);
2358 mime_part = tny_platform_factory_new_mime_part
2359 (modest_runtime_get_platform_factory ());
2361 /* try to get the attachment's size; this may fail for weird
2362 * file systems, like obex, upnp... */
2363 if (allowed_size != 0 &&
2364 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2366 if (size > allowed_size) {
2367 modest_platform_information_banner (NULL, NULL,
2368 dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2372 g_warning ("%s: could not get attachment size", __FUNCTION__);
2374 stream = create_stream_for_uri (uri);
2376 if (stream == NULL) {
2378 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2380 g_object_unref (mime_part);
2381 gnome_vfs_file_info_unref (info);
2385 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2386 g_object_unref (stream);
2388 content_id = g_strdup_printf ("%d", priv->next_cid);
2389 tny_mime_part_set_content_id (mime_part, content_id);
2390 g_free (content_id);
2393 basename = g_path_get_basename (filename);
2394 tny_mime_part_set_filename (mime_part, basename);
2397 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2398 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2400 info->size == 0, info->size);
2401 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2402 gtk_widget_show_all (priv->attachments_caption);
2403 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2405 g_object_unref (mime_part);
2406 gnome_vfs_file_info_unref (info);
2413 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2416 ModestMsgEditWindowPrivate *priv;
2419 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2420 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2422 if (att_list == NULL) {
2423 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2425 g_object_ref (att_list);
2428 if (tny_list_get_length (att_list) == 0) {
2429 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2431 gboolean dialog_response;
2432 gchar *message = NULL;
2433 gchar *filename = NULL;
2435 if (tny_list_get_length (att_list) == 1) {
2437 iter = tny_list_create_iterator (att_list);
2438 part = (TnyMimePart *) tny_iterator_get_current (iter);
2439 g_object_unref (iter);
2440 if (TNY_IS_MSG (part)) {
2441 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2443 filename = tny_header_dup_subject (header);
2444 g_object_unref (header);
2446 if (filename == NULL) {
2447 filename = g_strdup (_("mail_va_no_subject"));
2450 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2452 g_object_unref (part);
2454 filename = g_strdup ("");
2456 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2457 tny_list_get_length (att_list)), filename);
2460 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2463 if (dialog_response != GTK_RESPONSE_OK) {
2464 g_object_unref (att_list);
2467 hildon_banner_show_information (NULL, NULL, _("mcen_me_inbox_remove_attachments"));
2469 for (iter = tny_list_create_iterator (att_list);
2470 !tny_iterator_is_done (iter);
2471 tny_iterator_next (iter)) {
2472 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2473 const gchar *att_id;
2474 tny_list_remove (priv->attachments, (GObject *) mime_part);
2476 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2478 if (tny_list_get_length (priv->attachments) == 0)
2479 gtk_widget_hide (priv->attachments_caption);
2480 att_id = tny_mime_part_get_content_id (mime_part);
2482 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2484 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2485 g_object_unref (mime_part);
2487 g_object_unref (iter);
2490 g_object_unref (att_list);
2492 /* if the last attachment has been removed, focus the Subject: field */
2493 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2494 gtk_widget_grab_focus (priv->subject_field);
2498 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2501 ModestMsgEditWindowPrivate *priv;
2502 GdkColor *new_color;
2503 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2505 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2506 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2509 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2511 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2513 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2515 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2520 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2523 ModestMsgEditWindowPrivate *priv;
2524 gint new_size_index;
2525 ModestMsgEditWindow *window;
2528 window = MODEST_MSG_EDIT_WINDOW (userdata);
2529 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2530 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2532 if (gtk_check_menu_item_get_active (menu_item)) {
2534 WPTextBufferFormat format;
2536 memset (&format, 0, sizeof (format));
2537 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2539 label = gtk_bin_get_child (GTK_BIN (menu_item));
2541 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2542 format.cs.font_size = TRUE;
2543 format.cs.text_position = TRUE;
2544 format.cs.font = TRUE;
2545 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2546 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2548 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2549 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2550 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2552 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2553 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2554 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2560 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2563 ModestMsgEditWindowPrivate *priv;
2564 gint new_font_index;
2565 ModestMsgEditWindow *window;
2568 window = MODEST_MSG_EDIT_WINDOW (userdata);
2569 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2570 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2572 if (gtk_check_menu_item_get_active (menu_item)) {
2575 label = gtk_bin_get_child (GTK_BIN (menu_item));
2577 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2579 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2580 GINT_TO_POINTER(new_font_index)))
2581 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2583 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2584 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2585 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2591 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2594 ModestMsgEditWindowPrivate *priv = NULL;
2595 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2597 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2598 if (!priv->update_caption_visibility)
2601 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2603 gtk_widget_show (priv->cc_caption);
2605 gtk_widget_hide (priv->cc_caption);
2607 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2611 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2614 ModestMsgEditWindowPrivate *priv = NULL;
2615 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2617 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2618 if (!priv->update_caption_visibility)
2621 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2623 gtk_widget_show (priv->bcc_caption);
2625 gtk_widget_hide (priv->bcc_caption);
2627 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2631 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2632 ModestRecptEditor *editor)
2634 ModestMsgEditWindowPrivate *priv;
2636 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2637 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2639 /* we check for low-mem; in that case, show a warning, and don't allow
2640 * for the addressbook
2642 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2645 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2647 if (editor == NULL) {
2648 GtkWidget *view_focus;
2649 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2651 /* This code should be kept in sync with ModestRecptEditor. The
2652 textview inside the recpt editor is the one that really gets the
2653 focus. As it's inside a scrolled window, and this one inside the
2654 hbox recpt editor inherits from, we'll need to go up in the
2655 hierarchy to know if the text view is part of the recpt editor
2656 or if it's a different text entry */
2658 if (gtk_widget_get_parent (view_focus)) {
2659 GtkWidget *first_parent;
2661 first_parent = gtk_widget_get_parent (view_focus);
2662 if (gtk_widget_get_parent (first_parent) &&
2663 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2664 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2669 editor = MODEST_RECPT_EDITOR (priv->to_field);
2673 modest_address_book_select_addresses (editor);
2678 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2680 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2682 modest_msg_edit_window_open_addressbook (window, NULL);
2686 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2687 gboolean show_toolbar)
2689 ModestWindowPrivate *parent_priv;
2691 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2692 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2694 /* We can not just use the code of
2695 modest_msg_edit_window_setup_toolbar because it has a
2696 mixture of both initialization and creation code. */
2698 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2700 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2704 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2705 TnyHeaderFlags priority_flags)
2707 ModestMsgEditWindowPrivate *priv;
2708 ModestWindowPrivate *parent_priv;
2710 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2712 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2713 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2715 if (priv->priority_flags != priority_flags) {
2716 GtkAction *priority_action = NULL;
2718 priv->priority_flags = priority_flags;
2720 switch (priority_flags) {
2721 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2722 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2723 MODEST_HEADER_ICON_HIGH,
2724 HILDON_ICON_SIZE_XSMALL);
2725 gtk_widget_show (priv->priority_icon);
2726 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2727 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2729 case TNY_HEADER_FLAG_LOW_PRIORITY:
2730 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2731 MODEST_HEADER_ICON_LOW,
2732 HILDON_ICON_SIZE_XSMALL);
2733 gtk_widget_show (priv->priority_icon);
2734 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2735 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2738 gtk_widget_hide (priv->priority_icon);
2739 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2740 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2743 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2744 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2749 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2752 ModestMsgEditWindowPrivate *priv;
2753 ModestWindowPrivate *parent_priv;
2754 gint current_format;
2756 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2758 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2759 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2761 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2762 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2764 if (current_format != file_format) {
2765 switch (file_format) {
2766 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2767 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2768 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2770 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2774 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2775 response = gtk_dialog_run (GTK_DIALOG (dialog));
2776 gtk_widget_destroy (dialog);
2777 if (response == GTK_RESPONSE_OK) {
2778 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2780 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2781 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2786 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2787 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2788 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2793 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2796 ModestMsgEditWindowPrivate *priv;
2797 WPTextBufferFormat oldfmt, fmt;
2798 gint old_position = 0;
2802 GdkColor *color = NULL;
2803 gboolean bold, bold_set, italic, italic_set;
2804 gboolean underline, underline_set;
2805 gboolean strikethrough, strikethrough_set;
2806 gboolean position_set;
2807 gboolean font_size_set, font_set, color_set;
2810 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2811 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2813 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2814 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2815 GTK_WINDOW(dialog), GTK_WINDOW (window));
2817 /* First we get the currently selected font information */
2818 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2820 switch (oldfmt.text_position) {
2821 case TEXT_POSITION_NORMAL:
2824 case TEXT_POSITION_SUPERSCRIPT:
2832 g_object_set (G_OBJECT (dialog),
2833 "bold", oldfmt.bold != FALSE,
2834 "bold-set", !oldfmt.cs.bold,
2835 "underline", oldfmt.underline != FALSE,
2836 "underline-set", !oldfmt.cs.underline,
2837 "italic", oldfmt.italic != FALSE,
2838 "italic-set", !oldfmt.cs.italic,
2839 "strikethrough", oldfmt.strikethrough != FALSE,
2840 "strikethrough-set", !oldfmt.cs.strikethrough,
2841 "color", &oldfmt.color,
2842 "color-set", !oldfmt.cs.color,
2843 "size", wp_font_size[oldfmt.font_size],
2844 "size-set", !oldfmt.cs.font_size,
2845 "position", old_position,
2846 "position-set", !oldfmt.cs.text_position,
2847 "family", wp_get_font_name (oldfmt.font),
2848 "family-set", !oldfmt.cs.font,
2851 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2852 GTK_WINDOW (dialog), GTK_WINDOW (window));
2853 gtk_widget_show_all (dialog);
2854 priv->font_dialog = dialog;
2855 response = gtk_dialog_run (GTK_DIALOG (dialog));
2856 priv->font_dialog = NULL;
2857 if (response == GTK_RESPONSE_OK) {
2859 g_object_get( dialog,
2861 "bold-set", &bold_set,
2862 "underline", &underline,
2863 "underline-set", &underline_set,
2865 "italic-set", &italic_set,
2866 "strikethrough", &strikethrough,
2867 "strikethrough-set", &strikethrough_set,
2869 "color-set", &color_set,
2871 "size-set", &font_size_set,
2872 "family", &font_name,
2873 "family-set", &font_set,
2874 "position", &position,
2875 "position-set", &position_set,
2880 if (response == GTK_RESPONSE_OK) {
2881 memset(&fmt, 0, sizeof(fmt));
2887 fmt.italic = italic;
2888 fmt.cs.italic = TRUE;
2890 if (underline_set) {
2891 fmt.underline = underline;
2892 fmt.cs.underline = TRUE;
2894 if (strikethrough_set) {
2895 fmt.strikethrough = strikethrough;
2896 fmt.cs.strikethrough = TRUE;
2901 ? TEXT_POSITION_NORMAL
2902 : ( ( position == 1 )
2903 ? TEXT_POSITION_SUPERSCRIPT
2904 : TEXT_POSITION_SUBSCRIPT );
2905 fmt.cs.text_position = TRUE;
2906 fmt.font_size = oldfmt.font_size;
2910 fmt.cs.color = TRUE;
2913 fmt.font = wp_get_font_index(font_name,
2918 if (font_size_set) {
2919 fmt.cs.font_size = TRUE;
2920 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2922 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2923 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2925 gtk_widget_destroy (dialog);
2927 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2931 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2933 ModestMsgEditWindowPrivate *priv;
2935 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2936 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2938 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2940 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2941 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2945 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2947 ModestMsgEditWindowPrivate *priv;
2949 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2950 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2952 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2954 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2955 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2960 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2962 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2964 priv->can_undo = can_undo;
2968 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2970 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2972 priv->can_redo = can_redo;
2976 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2978 ModestMsgEditWindowPrivate *priv;
2979 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2980 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2982 return priv->can_undo;
2986 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2988 ModestMsgEditWindowPrivate *priv;
2989 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2990 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2992 return priv->can_redo;
2997 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3000 GtkTextIter match_start, match_end;
3002 if (image_id == NULL)
3005 gtk_text_buffer_get_start_iter (buffer, &iter);
3007 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3008 GSList *tags = gtk_text_iter_get_tags (&match_start);
3010 for (node = tags; node != NULL; node = g_slist_next (node)) {
3011 GtkTextTag *tag = (GtkTextTag *) node->data;
3012 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3013 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3014 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3016 offset = gtk_text_iter_get_offset (&match_start);
3017 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3018 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3022 gtk_text_iter_forward_char (&iter);
3027 message_is_empty (ModestMsgEditWindow *window)
3029 ModestMsgEditWindowPrivate *priv = NULL;
3031 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3032 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3034 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3035 * so we can ignore markup.
3037 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3040 count = gtk_text_buffer_get_char_count (buf);
3046 msg_body_focus (GtkWidget *focus,
3047 GdkEventFocus *event,
3051 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3052 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3053 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3058 recpt_field_changed (GtkTextBuffer *buffer,
3059 ModestMsgEditWindow *editor)
3061 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3062 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3066 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3068 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3069 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3073 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3076 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3077 GtkTextBuffer *buffer;
3079 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3080 gtk_text_buffer_set_modified (buffer, modified);
3081 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3082 gtk_text_buffer_set_modified (buffer, modified);
3083 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3084 gtk_text_buffer_set_modified (buffer, modified);
3085 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3089 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3091 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3092 const char *account_name;
3093 GtkTextBuffer *buffer;
3095 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3096 if (gtk_text_buffer_get_modified (buffer))
3098 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3099 if (gtk_text_buffer_get_modified (buffer))
3101 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3102 if (gtk_text_buffer_get_modified (buffer))
3104 if (gtk_text_buffer_get_modified (priv->text_buffer))
3106 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3107 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3118 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3120 ModestMsgEditWindowPrivate *priv = NULL;
3122 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3123 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3125 /* check if there's no recipient added */
3126 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3127 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3128 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3129 /* no recipient contents, then select contacts */
3130 modest_msg_edit_window_open_addressbook (window, NULL);
3134 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3135 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3138 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3139 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3142 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3143 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3147 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3148 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3149 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3156 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3157 ModestMsgEditWindow *window)
3159 modest_msg_edit_window_offer_attach_file (window);
3163 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3165 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3167 return priv->clipboard_text;
3171 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3173 ModestMsgEditWindow *window)
3175 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3176 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3178 if (!GTK_WIDGET_VISIBLE (window))
3181 g_object_ref (window);
3182 text = gtk_clipboard_wait_for_text (selection_clipboard);
3184 if (priv->clipboard_text != NULL) {
3185 g_free (priv->clipboard_text);
3187 priv->clipboard_text = text;
3189 if (GTK_WIDGET_VISIBLE (window)) {
3190 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3192 g_object_unref (window);
3195 static gboolean clipboard_owner_change_idle (gpointer userdata)
3197 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3198 ModestMsgEditWindowPrivate *priv;
3200 gdk_threads_enter ();
3201 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3202 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3204 priv->clipboard_owner_idle = 0;
3205 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3206 gdk_threads_leave ();
3212 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3214 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3215 if (priv->clipboard_owner_idle == 0) {
3216 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3221 subject_field_move_cursor (GtkEntry *entry,
3222 GtkMovementStep step,
3227 if (!GTK_WIDGET_VISIBLE (window))
3230 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3234 update_window_title (ModestMsgEditWindow *window)
3236 ModestMsgEditWindowPrivate *priv = NULL;
3237 const gchar *subject;
3239 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3240 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3241 if (subject == NULL || subject[0] == '\0')
3242 subject = _("mail_va_new_email");
3244 gtk_window_set_title (GTK_WINDOW (window), subject);
3249 subject_field_changed (GtkEditable *editable,
3250 ModestMsgEditWindow *window)
3252 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3253 update_window_title (window);
3254 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3255 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3256 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3260 subject_field_insert_text (GtkEditable *editable,
3262 gint new_text_length,
3264 ModestMsgEditWindow *window)
3266 GString *result = g_string_new ("");
3268 gint result_len = 0;
3269 const gchar *entry_text = NULL;
3272 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3273 old_length = g_utf8_strlen (entry_text, -1);
3275 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3276 gunichar c = g_utf8_get_char_validated (current, 8);
3277 /* Invalid unichar, stop */
3283 result = g_string_append_unichar (result, c);
3287 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3288 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3291 /* Prevent endless recursion */
3292 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3293 g_signal_emit_by_name (editable, "insert-text",
3294 (gpointer) result->str, (gpointer) result->len,
3295 (gpointer) position, (gpointer) window);
3296 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3300 if (result_len + old_length > 1000) {
3301 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3302 dgettext("hildon-common-strings",
3303 "ckdg_ib_maximum_characters_reached"));
3306 g_string_free (result, TRUE);
3310 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3313 ModestMsgEditWindowPrivate *priv = NULL;
3315 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3316 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3318 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3321 gtk_widget_show_all (priv->find_toolbar);
3322 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3324 gtk_widget_hide_all (priv->find_toolbar);
3325 gtk_widget_grab_focus (priv->msg_body);
3331 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3333 GtkTextIter *match_start,
3334 GtkTextIter *match_end)
3336 GtkTextIter end_iter;
3337 gchar *str_casefold;
3340 gchar *range_casefold;
3343 gboolean result = FALSE;
3350 gtk_text_iter_forward_to_end (&end_iter);
3352 str_casefold = g_utf8_casefold (str, -1);
3353 str_chars_n = strlen (str);
3355 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3356 range_casefold = g_utf8_casefold (range_text, -1);
3357 range_chars_n = strlen (range_casefold);
3359 if (range_chars_n < str_chars_n) {
3360 g_free (str_casefold);
3361 g_free (range_text);
3362 g_free (range_casefold);
3366 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3367 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3368 if (!g_utf8_collate (range_subtext, str_casefold)) {
3369 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3371 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3372 match_start, match_end, NULL);
3373 g_free (found_text);
3375 g_free (range_subtext);
3379 g_free (str_casefold);
3380 g_free (range_text);
3381 g_free (range_casefold);
3388 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3389 ModestMsgEditWindow *window)
3391 gchar *current_search = NULL;
3392 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3394 GtkTextIter selection_start, selection_end;
3395 GtkTextIter match_start, match_end;
3396 gboolean continue_search = FALSE;
3398 if (message_is_empty (window)) {
3399 g_free (priv->last_search);
3400 priv->last_search = NULL;
3401 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3405 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3406 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3407 g_free (current_search);
3408 g_free (priv->last_search);
3409 priv->last_search = NULL;
3410 /* Information banner about empty search */
3411 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3415 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3416 continue_search = TRUE;
3418 g_free (priv->last_search);
3419 priv->last_search = g_strdup (current_search);
3422 if (continue_search) {
3423 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3424 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3425 &match_start, &match_end);
3427 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3429 GtkTextIter buffer_start;
3430 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3431 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3432 &match_start, &match_end);
3434 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3437 /* Mark as selected the string found in search */
3439 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3440 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3441 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3443 g_free (priv->last_search);
3444 priv->last_search = NULL;
3446 g_free (current_search);
3450 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3451 ModestMsgEditWindow *window)
3453 GtkToggleAction *toggle;
3454 ModestWindowPrivate *parent_priv;
3455 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3457 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3458 gtk_toggle_action_set_active (toggle, FALSE);
3462 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3464 ModestMsgEditWindowPrivate *priv;
3466 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3471 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3474 ModestMsgEditWindowPrivate *priv;
3476 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3482 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3485 ModestMsgEditWindowPrivate *priv;
3486 TnyHeader *header = NULL;
3488 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3489 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3491 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3492 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3494 if (priv->draft_msg != NULL) {
3495 g_object_unref (priv->draft_msg);
3498 if (draft != NULL) {
3499 g_object_ref (draft);
3500 header = tny_msg_get_header (draft);
3501 if (priv->msg_uid) {
3502 g_free (priv->msg_uid);
3503 priv->msg_uid = NULL;
3505 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3506 if (GTK_WIDGET_REALIZED (window)) {
3507 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3508 gtk_widget_destroy (GTK_WIDGET (window));
3514 priv->draft_msg = draft;
3518 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3519 GtkTextIter *start, GtkTextIter *end,
3522 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3523 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3526 if (tag == NULL) return;
3527 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3528 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3529 replace_with_images (window, priv->images);
3534 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3537 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3539 g_return_if_fail (TNY_IS_MIME_PART (part));
3540 tny_list_prepend (priv->attachments, (GObject *) part);
3541 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3542 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3543 gtk_widget_show_all (priv->attachments_caption);
3544 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3548 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3550 ModestMsgEditWindowPrivate *priv;
3552 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3553 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3555 return priv->msg_uid;
3559 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3560 ModestMsgEditWindowWidgetType widget_type)
3562 ModestMsgEditWindowPrivate *priv;
3564 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3565 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3567 switch (widget_type) {
3568 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3569 return priv->msg_body;
3571 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3572 return priv->to_field;
3574 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3575 return priv->cc_field;
3577 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3578 return priv->bcc_field;
3580 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3581 return priv->subject_field;
3583 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3584 return priv->attachments_view;
3592 remove_tags (WPTextBuffer *buffer)
3594 GtkTextIter start, end;
3596 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3597 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3599 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3603 on_account_removed (TnyAccountStore *account_store,
3604 TnyAccount *account,
3607 /* Do nothing if it's a store account, because we use the
3608 transport to send the messages */
3609 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3610 const gchar *parent_acc = NULL;
3611 const gchar *our_acc = NULL;
3613 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3614 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3615 /* Close this window if I'm showing a message of the removed account */
3616 if (strcmp (parent_acc, our_acc) == 0)
3617 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3622 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3624 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3626 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3632 set_zoom_do_nothing (ModestWindow *window,
3638 get_zoom_do_nothing (ModestWindow *window)
3643 typedef struct _MessageSettingsHelper {
3644 ModestMsgEditWindow *window;
3645 GSList *priority_group;
3646 GtkWidget *align_picker;
3647 } MessageSettingsHelper;
3650 on_priority_toggle (HildonCheckButton *button,
3651 MessageSettingsHelper *helper)
3654 ModestMsgEditWindowPrivate *priv;
3656 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3657 if (hildon_check_button_get_active (button)) {
3659 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3660 HildonCheckButton *node_button = (HildonCheckButton *) node->data;
3661 if ((node_button != button) &&
3662 hildon_check_button_get_active (node_button)) {
3663 hildon_check_button_set_active (node_button, FALSE);
3665 if (priv->priority_flags != (TnyHeaderFlags) g_object_get_data (G_OBJECT (button), "priority"))
3666 modest_msg_edit_window_set_priority_flags (helper->window,
3668 g_object_get_data (G_OBJECT (button),
3674 gboolean found = FALSE;
3675 /* If no one is active, activate it again */
3676 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3677 HildonCheckButton *node_button = (HildonCheckButton *) node->data;
3678 if (hildon_check_button_get_active (node_button)) {
3684 hildon_check_button_set_active (button, TRUE);
3690 on_format_picker_value_changed (HildonPickerButton *button,
3691 MessageSettingsHelper *helper)
3693 ModestMsgEditFormat new_format, old_format;
3696 switch (hildon_picker_button_get_active (button)) {
3698 new_format = MODEST_MSG_EDIT_FORMAT_HTML;
3699 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
3703 new_format = MODEST_MSG_EDIT_FORMAT_TEXT;
3704 file_format = MODEST_FILE_FORMAT_PLAIN_TEXT;
3708 old_format = modest_msg_edit_window_get_format (helper->window);
3709 if (new_format != old_format) {
3710 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (helper->window), file_format);
3712 switch (modest_msg_edit_window_get_format (helper->window)) {
3713 case MODEST_MSG_EDIT_FORMAT_TEXT:
3714 hildon_picker_button_set_active (button, 0);
3715 gtk_widget_set_sensitive (helper->align_picker, FALSE);
3717 case MODEST_MSG_EDIT_FORMAT_HTML:
3719 hildon_picker_button_set_active (button, 1);
3720 gtk_widget_set_sensitive (helper->align_picker, TRUE);
3727 on_align_picker_value_changed (HildonPickerButton *button,
3728 MessageSettingsHelper *helper)
3730 GtkJustification new_justify;
3731 ModestMsgEditFormatState *format_state = NULL;
3733 switch (hildon_picker_button_get_active (button)) {
3735 new_justify = GTK_JUSTIFY_CENTER;
3738 new_justify = GTK_JUSTIFY_RIGHT;
3742 new_justify = GTK_JUSTIFY_LEFT;
3746 format_state = modest_msg_edit_window_get_format_state (helper->window);
3747 if (format_state->justification != new_justify)
3748 format_state->justification = new_justify;
3749 modest_msg_edit_window_set_format_state (helper->window, format_state);
3750 g_free (format_state);
3754 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3758 GtkWidget *priority_hbox;
3759 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3760 GtkWidget *captioned;
3761 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3762 GtkWidget *format_picker;
3763 GtkWidget *format_selector;
3764 GtkWidget *align_selector;
3765 ModestMsgEditWindowPrivate *priv;
3766 MessageSettingsHelper helper = {0,};
3767 ModestMsgEditFormatState *format_state = NULL;
3769 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3770 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3771 helper.window = window;
3772 helper.priority_group = NULL;
3774 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3775 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3777 dialog = gtk_dialog_new ();
3778 vbox = gtk_vbox_new (FALSE, 0);
3779 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3780 gtk_widget_show (vbox);
3782 /* Priority toggles */
3783 priority_hbox = gtk_hbox_new (TRUE, 0);
3784 high_toggle = hildon_check_button_new (HILDON_SIZE_FINGER_HEIGHT);
3785 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3786 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3787 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3788 medium_toggle = hildon_check_button_new (HILDON_SIZE_FINGER_HEIGHT);
3789 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3790 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3791 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3792 low_toggle = hildon_check_button_new (HILDON_SIZE_FINGER_HEIGHT);
3793 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3794 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3795 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3796 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, FALSE, FALSE, 0);
3797 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, FALSE, FALSE, 0);
3798 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, FALSE, FALSE, 0);
3799 gtk_widget_show_all (priority_hbox);
3800 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3801 _("mcen_me_editor_message_priority"), priority_hbox);
3802 gtk_widget_show (captioned);
3803 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3805 /* format selector */
3806 format_selector = hildon_touch_selector_new_text ();
3807 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (format_selector), _("mcen_me_editor_plain_text"));
3808 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (format_selector), _("mcen_me_editor_formatted_text"));
3809 format_picker = hildon_picker_button_new (MODEST_EDITABLE_SIZE,
3810 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
3811 hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (format_picker), HILDON_TOUCH_SELECTOR (format_selector));
3812 modest_maemo_utils_set_hbutton_layout (title_sizegroup, value_sizegroup,
3813 _("mcen_me_editor_format"), format_picker);
3814 gtk_widget_show_all (format_picker);
3815 gtk_box_pack_start (GTK_BOX (vbox), format_picker, FALSE, FALSE, 0);
3817 /* alignment selector */
3818 align_selector = hildon_touch_selector_new_text ();
3819 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (align_selector), _("mcen_me_editor_align_left"));
3820 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (align_selector), _("mcen_me_editor_align_centred"));
3821 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (align_selector), _("mcen_me_editor_align_right"));
3822 helper.align_picker = hildon_picker_button_new (MODEST_EDITABLE_SIZE,
3823 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
3824 hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (helper.align_picker), HILDON_TOUCH_SELECTOR (align_selector));
3825 modest_maemo_utils_set_hbutton_layout (title_sizegroup, value_sizegroup,
3826 _("mcen_me_editor_align"), helper.align_picker);
3827 gtk_widget_show_all (helper.align_picker);
3828 gtk_box_pack_start (GTK_BOX (vbox), helper.align_picker, FALSE, FALSE, 0);
3830 g_object_unref (title_sizegroup);
3831 g_object_unref (value_sizegroup);
3832 gtk_window_set_title (GTK_WINDOW (dialog), _("TODO: Message settings"));
3834 /* Set current values */
3835 switch (priv->priority_flags) {
3836 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3837 hildon_check_button_set_active (HILDON_CHECK_BUTTON (high_toggle), TRUE);
3839 case TNY_HEADER_FLAG_LOW_PRIORITY:
3840 hildon_check_button_set_active (HILDON_CHECK_BUTTON (low_toggle), TRUE);
3843 hildon_check_button_set_active (HILDON_CHECK_BUTTON (medium_toggle), TRUE);
3847 switch (modest_msg_edit_window_get_format (window)) {
3848 case MODEST_MSG_EDIT_FORMAT_TEXT:
3849 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (format_picker), 0);
3850 gtk_widget_set_sensitive (helper.align_picker, FALSE);
3852 case MODEST_MSG_EDIT_FORMAT_HTML:
3854 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (format_picker), 1);
3855 gtk_widget_set_sensitive (helper.align_picker, TRUE);
3859 format_state = modest_msg_edit_window_get_format_state (window);
3860 switch (format_state->justification) {
3861 case GTK_JUSTIFY_RIGHT:
3862 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 2);
3864 case GTK_JUSTIFY_CENTER:
3865 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 1);
3868 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 0);
3872 g_free (format_state);
3874 /* Signal connects */
3875 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3876 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3877 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3878 g_signal_connect (G_OBJECT (format_picker), "value-changed", G_CALLBACK (on_format_picker_value_changed), &helper);
3879 g_signal_connect (G_OBJECT (helper.align_picker), "value-changed",
3880 G_CALLBACK (on_align_picker_value_changed), &helper);
3882 gtk_dialog_run (GTK_DIALOG (dialog));
3884 /* Read new values */
3886 gtk_widget_destroy (dialog);
3887 g_slist_free (helper.priority_group);
3891 static void on_message_settings (GtkAction *action,
3892 ModestMsgEditWindow *window)
3894 modest_msg_edit_window_show_msg_settings_dialog (window);
3898 static void add_button_to_menu (ModestMsgEditWindow *self,
3899 HildonAppMenu *menu,
3901 ModestDimmingRulesGroup *group,
3902 GCallback dimming_callback)
3904 if (dimming_callback)
3905 modest_dimming_rules_group_add_widget_rule (group,
3906 GTK_WIDGET (button),
3908 MODEST_WINDOW (self));
3909 hildon_app_menu_append (menu, GTK_BUTTON (button));
3912 static void add_to_menu (ModestMsgEditWindow *self,
3913 HildonAppMenu *menu,
3916 ModestDimmingRulesGroup *group,
3917 GCallback dimming_callback)
3921 button = gtk_button_new_with_label (label);
3922 g_signal_connect_after (G_OBJECT (button), "clicked",
3923 callback, (gpointer) self);
3924 add_button_to_menu (self, menu, GTK_BUTTON (button), group, dimming_callback);
3928 setup_menu (ModestMsgEditWindow *self, ModestDimmingRulesGroup *group)
3930 ModestMsgEditWindowPrivate *priv = NULL;
3932 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3934 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3936 priv->app_menu = hildon_app_menu_new ();
3938 /* Settings menu buttons */
3939 add_to_menu (self, HILDON_APP_MENU (priv->app_menu), _("mcen_me_editor_checknames"),
3940 G_CALLBACK (modest_ui_actions_on_check_names),
3942 add_to_menu (self, HILDON_APP_MENU (priv->app_menu), _("mcen_me_inbox_undo"),
3943 G_CALLBACK (modest_ui_actions_on_undo),
3946 priv->cc_button = hildon_check_button_new (0);
3947 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("TODO: Show CC"));
3948 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3950 add_button_to_menu (self, HILDON_APP_MENU (priv->app_menu), GTK_BUTTON (priv->cc_button),
3952 priv->bcc_button = hildon_check_button_new (0);
3953 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("TODO: Show BCC"));
3954 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3956 add_button_to_menu (self, HILDON_APP_MENU (priv->app_menu), GTK_BUTTON (priv->bcc_button),
3959 add_to_menu (self, HILDON_APP_MENU (priv->app_menu), _("mcen_me_editor_attach_inlineimage"),
3960 G_CALLBACK (modest_ui_actions_on_insert_image),
3962 add_to_menu (self, HILDON_APP_MENU (priv->app_menu), _("mcen_me_inbox_remove_attachments"),
3963 G_CALLBACK (modest_ui_actions_on_remove_attachments),
3965 add_to_menu (self, HILDON_APP_MENU (priv->app_menu), _("TODO: Message settings..."),
3966 G_CALLBACK (on_message_settings),
3969 /* TODO: find in toolbar check button */
3971 hildon_stackable_window_set_main_menu (HILDON_STACKABLE_WINDOW (self),
3972 HILDON_APP_MENU (priv->app_menu));
3976 modest_msg_edit_window_toggle_menu (HildonWindow *window,
3980 ModestMsgEditWindowPrivate *priv = NULL;
3982 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3984 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3986 gtk_widget_queue_resize (priv->app_menu);
3988 return HILDON_WINDOW_CLASS (parent_class)->toggle_menu (window, button, time);