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;
1140 gboolean field_view_set;
1142 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1143 g_return_if_fail (TNY_IS_MSG (msg));
1145 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1146 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1148 header = tny_msg_get_header (msg);
1149 to = tny_header_dup_to (header);
1150 cc = tny_header_dup_cc (header);
1151 bcc = tny_header_dup_bcc (header);
1152 subject = tny_header_dup_subject (header);
1153 priority_flags = tny_header_get_priority (header);
1156 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1158 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
1159 field_view_set = TRUE;
1161 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1162 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1163 gtk_widget_show (priv->cc_caption);
1164 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1165 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1166 gtk_widget_hide (priv->cc_caption);
1167 field_view_set = FALSE;
1170 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), field_view_set);
1172 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
1173 field_view_set = TRUE;
1175 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1176 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1177 gtk_widget_show (priv->bcc_caption);
1178 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1179 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1180 gtk_widget_hide (priv->bcc_caption);
1181 field_view_set = FALSE;
1184 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), field_view_set);
1188 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1189 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1192 update_window_title (self);
1194 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1195 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1197 if ((body == NULL)||(body[0] == '\0')) {
1199 body = modest_text_utils_convert_to_html ("");
1202 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1203 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1206 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1209 /* Add attachments to the view */
1210 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1211 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1212 if (tny_list_get_length (priv->attachments) == 0) {
1213 gtk_widget_hide (priv->attachments_caption);
1215 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1216 gtk_widget_show_all (priv->attachments_caption);
1218 get_related_images (self, msg);
1219 update_next_cid (self, priv->attachments);
1220 update_next_cid (self, priv->images);
1221 replace_with_images (self, priv->images);
1223 if (preserve_is_rich && !is_html) {
1224 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1225 /* Get the default format required from configuration */
1226 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1227 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1230 /* Set the default focus depending on having already a To: field or not */
1231 if ((!to)||(*to == '\0')) {
1232 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1234 gtk_widget_grab_focus (priv->msg_body);
1237 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1239 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1240 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1242 modest_msg_edit_window_set_modified (self, FALSE);
1244 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1245 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1246 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1247 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1249 if (priv->msg_uid) {
1250 g_free (priv->msg_uid);
1251 priv->msg_uid = NULL;
1254 /* we should set a reference to the incoming message if it is a draft */
1255 msg_folder = tny_msg_get_folder (msg);
1257 if (modest_tny_folder_is_local_folder (msg_folder)) {
1258 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1259 if (type == TNY_FOLDER_TYPE_INVALID)
1260 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1262 if (type == TNY_FOLDER_TYPE_DRAFTS)
1263 priv->draft_msg = g_object_ref(msg);
1264 if (type == TNY_FOLDER_TYPE_OUTBOX)
1265 priv->outbox_msg = g_object_ref(msg);
1266 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1268 g_object_unref (msg_folder);
1278 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1281 GList *item_children, *node;
1282 GtkWidget *bin_child;
1284 bin_child = gtk_bin_get_child (GTK_BIN(item));
1286 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1288 for (node = item_children; node != NULL; node = g_list_next (node)) {
1289 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1290 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1293 g_list_free (item_children);
1297 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1300 GList *item_children, *node;
1302 box = gtk_bin_get_child (GTK_BIN (item));
1303 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1304 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1306 for (node = item_children; node != NULL; node = g_list_next (node)) {
1307 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1308 if (GTK_IS_TOGGLE_BUTTON (node->data))
1309 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1310 else if (GTK_IS_BUTTON (node->data))
1311 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1313 g_list_free (item_children);
1318 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1320 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1321 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1322 GtkWidget *placeholder;
1323 GtkWidget *tool_item;
1328 GtkWidget *sizes_menu;
1329 GtkWidget *fonts_menu;
1330 GSList *radio_group = NULL;
1331 GSList *node = NULL;
1335 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1336 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1338 /* Font color placeholder */
1339 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1340 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1343 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1344 priv->font_color_button = hildon_color_button_new ();
1345 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1346 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1347 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1348 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1349 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1350 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1351 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1353 G_CALLBACK (modest_msg_edit_window_color_button_change),
1356 /* Font size and face placeholder */
1357 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1358 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1360 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1361 priv->size_tool_button_label = gtk_label_new (NULL);
1362 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1363 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1364 size_text,"</span>", NULL);
1365 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1367 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1368 sizes_menu = gtk_menu_new ();
1369 priv->size_items_group = NULL;
1371 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1372 GtkWidget *size_menu_item;
1374 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1375 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1376 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1377 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1378 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1379 gtk_widget_show (size_menu_item);
1381 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1385 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1386 GtkWidget *item = (GtkWidget *) node->data;
1387 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1391 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1392 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1393 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1394 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1395 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1396 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1397 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1398 priv->font_size_toolitem = tool_item;
1401 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1402 priv->font_tool_button_label = gtk_label_new (NULL);
1403 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1404 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1406 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1407 fonts_menu = gtk_menu_new ();
1408 priv->font_items_group = NULL;
1410 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1411 GtkWidget *font_menu_item;
1412 GtkWidget *child_label;
1414 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1415 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1416 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1417 wp_get_font_name (font_index), "</span>", NULL);
1418 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1421 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1422 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1423 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1424 gtk_widget_show (font_menu_item);
1426 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1429 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1430 GtkWidget *item = (GtkWidget *) node->data;
1431 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1434 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1435 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1436 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1437 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1438 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1439 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1440 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1441 priv->font_face_toolitem = tool_item;
1443 /* Set expand and homogeneous for remaining items */
1444 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1445 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1446 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1447 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1448 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1449 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1450 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1451 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1452 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1454 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1455 will not show the tool items added to the placeholders) */
1456 gtk_widget_show_all (parent_priv->toolbar);
1458 /* Set the no show all *after* showing all items. We do not
1459 want the toolbar to be shown with a show all because it
1460 could go agains the gconf setting regarding showing or not
1461 the toolbar of the editor window */
1462 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1468 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1471 ModestWindowPrivate *parent_priv;
1472 ModestMsgEditWindowPrivate *priv;
1473 ModestDimmingRulesGroup *menu_rules_group = NULL;
1474 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1475 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1476 ModestWindowMgr *mgr = NULL;
1478 g_return_val_if_fail (msg, NULL);
1479 g_return_val_if_fail (account_name, NULL);
1481 mgr = modest_runtime_get_window_mgr ();
1483 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1485 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1486 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1488 /* Menubar. Update the state of some toggles */
1489 priv->from_field_protos = get_transports ();
1490 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1491 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1492 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1494 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1495 hildon_touch_selector_get_current_text
1496 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1497 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1498 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1501 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1503 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1505 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1507 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1509 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1510 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1511 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1512 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1513 /* Add common dimming rules */
1514 modest_dimming_rules_group_add_rules (menu_rules_group,
1515 modest_msg_edit_window_menu_dimming_entries,
1516 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1517 MODEST_WINDOW (obj));
1518 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1519 modest_msg_edit_window_toolbar_dimming_entries,
1520 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1521 MODEST_WINDOW (obj));
1522 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1523 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1524 MODEST_WINDOW (obj));
1525 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1526 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1527 MODEST_WINDOW (obj));
1528 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1529 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1530 MODEST_WINDOW (obj));
1531 /* Insert dimming rules group for this window */
1532 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1533 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1534 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1536 /* Setup app menu */
1537 setup_menu (MODEST_MSG_EDIT_WINDOW (obj), menu_rules_group);
1539 /* Checks the dimming rules */
1540 g_object_unref (menu_rules_group);
1541 g_object_unref (toolbar_rules_group);
1542 g_object_unref (clipboard_rules_group);
1543 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1545 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1547 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1548 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1549 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1550 priv->update_caption_visibility = TRUE;
1552 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1554 /* Track account-removed signal, this window should be closed
1555 in the case we're creating a mail associated to the account
1557 priv->account_removed_handler_id =
1558 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1560 G_CALLBACK(on_account_removed),
1563 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1565 return (ModestWindow*) obj;
1569 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1571 GString **string_buffer = (GString **) user_data;
1573 *string_buffer = g_string_append (*string_buffer, buffer);
1579 * @result: A new string which should be freed with g_free().
1582 get_formatted_data (ModestMsgEditWindow *edit_window)
1584 ModestMsgEditWindowPrivate *priv;
1585 GString *string_buffer = g_string_new ("");
1587 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1589 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1591 modest_text_utils_hyperlinkify (string_buffer);
1593 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1595 return g_string_free (string_buffer, FALSE);
1600 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1603 const gchar *account_name;
1604 ModestMsgEditWindowPrivate *priv;
1605 TnyIterator *att_iter;
1607 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1609 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1611 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1612 g_return_val_if_fail (account_name, NULL);
1615 /* don't free these (except from) */
1616 data = g_slice_new0 (MsgData);
1617 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1619 data->account_name = g_strdup (account_name);
1620 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1621 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1622 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1623 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1624 if (priv->draft_msg) {
1625 data->draft_msg = g_object_ref (priv->draft_msg);
1626 } else if (priv->outbox_msg) {
1627 data->draft_msg = g_object_ref (priv->outbox_msg);
1629 data->draft_msg = NULL;
1632 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1634 gtk_text_buffer_get_bounds (buf, &b, &e);
1635 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1637 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1638 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1640 data->html_body = NULL;
1642 /* deep-copy the data */
1643 att_iter = tny_list_create_iterator (priv->attachments);
1644 data->attachments = NULL;
1645 while (!tny_iterator_is_done (att_iter)) {
1646 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1647 if (!(TNY_IS_MIME_PART(part))) {
1648 g_warning ("strange data in attachment list");
1649 g_object_unref (part);
1650 tny_iterator_next (att_iter);
1653 data->attachments = g_list_append (data->attachments,
1655 tny_iterator_next (att_iter);
1657 g_object_unref (att_iter);
1659 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1660 att_iter = tny_list_create_iterator (priv->images);
1661 data->images = NULL;
1662 while (!tny_iterator_is_done (att_iter)) {
1663 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1665 if (!(TNY_IS_MIME_PART(part))) {
1666 g_warning ("strange data in attachment list");
1667 g_object_unref (part);
1668 tny_iterator_next (att_iter);
1671 cid = tny_mime_part_get_content_id (part);
1673 gchar *image_tag_id;
1674 GtkTextTag *image_tag;
1676 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1677 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1678 g_free (image_tag_id);
1680 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1682 ((gtk_text_iter_has_tag (&iter, image_tag))||
1683 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1684 data->images = g_list_append (data->images,
1685 g_object_ref (part));
1687 g_object_unref (part);
1688 tny_iterator_next (att_iter);
1690 g_object_unref (att_iter);
1692 data->priority_flags = priv->priority_flags;
1699 unref_gobject (GObject *obj, gpointer data)
1701 if (!G_IS_OBJECT(obj))
1703 g_object_unref (obj);
1707 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1710 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1718 g_free (data->from);
1719 g_free (data->subject);
1720 g_free (data->plain_body);
1721 g_free (data->html_body);
1722 g_free (data->account_name);
1724 if (data->draft_msg != NULL) {
1725 g_object_unref (data->draft_msg);
1726 data->draft_msg = NULL;
1729 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1730 g_list_free (data->attachments);
1731 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1732 g_list_free (data->images);
1734 g_slice_free (MsgData, data);
1738 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1740 guint64 *parts_size)
1742 ModestMsgEditWindowPrivate *priv;
1744 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1746 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1748 /* TODO: add images */
1749 *parts_size += priv->images_size;
1750 *parts_count += priv->images_count;
1755 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1758 ModestMsgEditWindowPrivate *priv = NULL;
1759 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1761 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1763 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1765 return MODEST_MSG_EDIT_FORMAT_HTML;
1767 return MODEST_MSG_EDIT_FORMAT_TEXT;
1771 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1772 ModestMsgEditFormat format)
1774 ModestMsgEditWindowPrivate *priv;
1776 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1777 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1780 case MODEST_MSG_EDIT_FORMAT_HTML:
1781 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1783 case MODEST_MSG_EDIT_FORMAT_TEXT:
1784 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1787 g_return_if_reached ();
1791 ModestMsgEditFormatState *
1792 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1794 ModestMsgEditFormatState *format_state = NULL;
1795 ModestMsgEditWindowPrivate *priv;
1796 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1798 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1799 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1801 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1803 format_state = g_new0 (ModestMsgEditFormatState, 1);
1804 format_state->bold = buffer_format->bold&0x1;
1805 format_state->italics = buffer_format->italic&0x1;
1806 format_state->bullet = buffer_format->bullet&0x1;
1807 format_state->color = buffer_format->color;
1808 format_state->font_size = buffer_format->font_size;
1809 format_state->font_family = wp_get_font_name (buffer_format->font);
1810 format_state->justification = buffer_format->justification;
1811 g_free (buffer_format);
1813 return format_state;
1818 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1819 const ModestMsgEditFormatState *format_state)
1821 ModestMsgEditWindowPrivate *priv;
1822 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1823 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1824 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1825 g_return_if_fail (format_state != NULL);
1827 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1828 gtk_widget_grab_focus (priv->msg_body);
1829 buffer_format->bold = (format_state->bold != FALSE);
1830 buffer_format->italic = (format_state->italics != FALSE);
1831 buffer_format->color = format_state->color;
1832 buffer_format->font_size = format_state->font_size;
1833 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1834 buffer_format->justification = format_state->justification;
1835 buffer_format->bullet = format_state->bullet;
1837 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1839 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1840 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1841 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1842 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1843 buffer_format->cs.font = (buffer_format->font != current_format->font);
1844 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1845 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1847 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1848 if (buffer_format->cs.bold) {
1849 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1850 GINT_TO_POINTER (buffer_format->bold&0x1));
1852 if (buffer_format->cs.italic) {
1853 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1854 GINT_TO_POINTER (buffer_format->italic&0x1));
1856 if (buffer_format->cs.color) {
1857 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1858 GINT_TO_POINTER (&(buffer_format->color)));
1860 if (buffer_format->cs.font_size) {
1861 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1862 GINT_TO_POINTER (buffer_format->font_size));
1864 if (buffer_format->cs.justification) {
1865 switch (buffer_format->justification) {
1866 case GTK_JUSTIFY_LEFT:
1867 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1868 GINT_TO_POINTER(TRUE));
1870 case GTK_JUSTIFY_CENTER:
1871 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1872 GINT_TO_POINTER(TRUE));
1874 case GTK_JUSTIFY_RIGHT:
1875 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1876 GINT_TO_POINTER(TRUE));
1883 if (buffer_format->cs.font) {
1884 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1885 GINT_TO_POINTER (buffer_format->font));
1887 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1888 if (buffer_format->cs.bullet) {
1889 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1890 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1892 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1894 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1896 g_free (buffer_format);
1897 g_free (current_format);
1899 /* Check dimming rules */
1900 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1901 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1905 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1907 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1909 ModestWindowPrivate *parent_priv;
1910 ModestMsgEditWindowPrivate *priv;
1911 GtkWidget *new_size_menuitem;
1912 GtkWidget *new_font_menuitem;
1914 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1915 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1917 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1918 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
1919 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1920 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1922 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
1923 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1924 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1927 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1929 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1930 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1932 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1933 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1935 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1936 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1939 switch (buffer_format->justification)
1941 case GTK_JUSTIFY_LEFT:
1942 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1944 case GTK_JUSTIFY_CENTER:
1945 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1947 case GTK_JUSTIFY_RIGHT:
1948 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1955 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1957 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1958 G_CALLBACK (modest_msg_edit_window_color_button_change),
1960 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1961 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1962 G_CALLBACK (modest_msg_edit_window_color_button_change),
1965 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1966 buffer_format->font_size))->data);
1967 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1971 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1972 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1973 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1975 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1976 G_CALLBACK (modest_msg_edit_window_size_change),
1978 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1979 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1980 G_CALLBACK (modest_msg_edit_window_size_change),
1984 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1985 buffer_format->font))->data);
1986 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1990 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1991 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1992 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1994 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1995 G_CALLBACK (modest_msg_edit_window_font_change),
1997 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1998 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1999 G_CALLBACK (modest_msg_edit_window_font_change),
2003 g_free (buffer_format);
2007 #ifdef MODEST_HILDON_VERSION_0
2009 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2012 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2013 ModestMsgEditWindowPrivate *priv;
2014 GtkWidget *dialog = NULL;
2016 GdkColor *new_color = NULL;
2018 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2019 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2021 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2022 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2023 g_free (buffer_format);
2025 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2026 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2027 if (new_color != NULL) {
2028 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2029 (gpointer) new_color);
2032 gtk_widget_destroy (dialog);
2037 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2040 ModestMsgEditWindowPrivate *priv;
2041 GtkWidget *dialog = NULL;
2043 GdkColor *old_color = NULL;
2044 const GdkColor *new_color = NULL;
2046 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2047 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2049 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2050 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2052 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2053 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2054 if (new_color != NULL)
2055 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2057 gtk_widget_destroy (dialog);
2063 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2066 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2067 ModestMsgEditWindowPrivate *priv;
2068 GtkWidget *dialog = NULL;
2070 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2071 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2073 dialog = hildon_color_chooser_new ();
2074 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2075 g_free (buffer_format);
2077 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2079 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2080 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2083 gtk_widget_destroy (dialog);
2088 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2091 ModestMsgEditWindowPrivate *priv;
2092 GtkWidget *dialog = NULL;
2093 GdkColor *old_color = NULL;
2095 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2096 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2098 dialog = hildon_color_chooser_new ();
2099 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2101 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2103 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2104 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2106 gtk_widget_destroy (dialog);
2109 #endif /*!MODEST_HILDON_VERSION_0*/
2114 create_stream_for_uri (const gchar* uri)
2119 TnyStream *result = NULL;
2121 GnomeVFSHandle *handle = NULL;
2122 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2123 if (test == GNOME_VFS_OK) {
2124 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2125 /* Streams over OBEX (Bluetooth) are not seekable but
2126 * we expect them to be (we might need to read them
2127 * several times). So if this is a Bluetooth URI just
2128 * read the whole file into memory (this is not a fast
2129 * protocol so we can assume that these files are not
2130 * going to be very big) */
2131 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2132 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2133 TnyStream *memstream = tny_camel_mem_stream_new ();
2134 tny_stream_write_to_stream (vfssstream, memstream);
2135 g_object_unref (vfssstream);
2138 result = vfssstream;
2146 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2149 ModestMsgEditWindowPrivate *priv;
2150 GtkWidget *dialog = NULL;
2152 GSList *uris = NULL;
2153 GSList *uri_node = NULL;
2155 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2157 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2158 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2159 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2161 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2163 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2164 GTK_WINDOW (dialog), GTK_WINDOW (window));
2166 response = gtk_dialog_run (GTK_DIALOG (dialog));
2168 case GTK_RESPONSE_OK:
2169 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2174 gtk_widget_destroy (dialog);
2176 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2178 GnomeVFSHandle *handle = NULL;
2179 GnomeVFSResult result;
2180 GtkTextIter position;
2181 GtkTextMark *insert_mark;
2183 uri = (const gchar *) uri_node->data;
2184 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2185 if (result == GNOME_VFS_OK) {
2187 GnomeVFSFileInfo *info;
2188 gchar *filename, *basename, *escaped_filename;
2189 TnyMimePart *mime_part;
2191 const gchar *mime_type = NULL;
2192 GnomeVFSURI *vfs_uri;
2193 guint64 stream_size;
2195 gnome_vfs_close (handle);
2196 vfs_uri = gnome_vfs_uri_new (uri);
2198 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2199 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2200 g_free (escaped_filename);
2201 gnome_vfs_uri_unref (vfs_uri);
2202 info = gnome_vfs_file_info_new ();
2204 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2205 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2207 mime_type = gnome_vfs_file_info_get_mime_type (info);
2209 mime_part = tny_platform_factory_new_mime_part
2210 (modest_runtime_get_platform_factory ());
2212 TnyStream *stream = create_stream_for_uri (uri);
2214 if (stream == NULL) {
2216 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2218 g_object_unref (mime_part);
2219 gnome_vfs_file_info_unref (info);
2223 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2225 content_id = g_strdup_printf ("%d", priv->next_cid);
2226 tny_mime_part_set_content_id (mime_part, content_id);
2227 g_free (content_id);
2230 basename = g_path_get_basename (filename);
2231 tny_mime_part_set_filename (mime_part, basename);
2234 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2236 if (pixbuf != NULL) {
2237 priv->images_size += stream_size;
2238 priv->images_count ++;
2239 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2240 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2241 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2242 g_object_unref (pixbuf);
2245 tny_list_prepend (priv->images, (GObject *) mime_part);
2246 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2248 g_object_unref (mime_part);
2249 gnome_vfs_file_info_unref (info);
2258 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2260 GtkWidget *dialog = NULL;
2262 GSList *uris = NULL;
2264 GnomeVFSFileSize total_size, allowed_size;
2265 ModestMsgEditWindowPrivate *priv;
2269 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2271 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2273 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2276 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2277 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2278 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2279 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), GTK_WINDOW (window));
2281 response = gtk_dialog_run (GTK_DIALOG (dialog));
2283 case GTK_RESPONSE_OK:
2284 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2289 gtk_widget_destroy (dialog);
2291 /* allowed size is the maximum size - what's already there */
2292 modest_attachments_view_get_sizes (
2293 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2294 &att_num, &att_size);
2295 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2298 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2300 const gchar *uri = (const gchar *) uri_node->data;
2302 total_size += modest_msg_edit_window_attach_file_one
2303 (window, uri, allowed_size);
2305 if (total_size > allowed_size) {
2306 g_warning ("%s: total size: %u",
2307 __FUNCTION__, (unsigned int)total_size);
2311 allowed_size -= total_size;
2315 g_slist_foreach (uris, (GFunc) g_free, NULL);
2316 g_slist_free (uris);
2321 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2323 GnomeVFSFileSize allowed_size)
2326 GnomeVFSHandle *handle = NULL;
2327 ModestMsgEditWindowPrivate *priv;
2328 GnomeVFSResult result;
2329 GnomeVFSFileSize size = 0;
2330 g_return_val_if_fail (window, 0);
2331 g_return_val_if_fail (uri, 0);
2333 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2335 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2336 if (result == GNOME_VFS_OK) {
2337 TnyMimePart *mime_part;
2339 const gchar *mime_type = NULL;
2341 gchar *escaped_filename;
2344 GnomeVFSFileInfo *info;
2345 GnomeVFSURI *vfs_uri;
2347 gnome_vfs_close (handle);
2348 vfs_uri = gnome_vfs_uri_new (uri);
2351 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2352 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2353 g_free (escaped_filename);
2354 gnome_vfs_uri_unref (vfs_uri);
2356 info = gnome_vfs_file_info_new ();
2358 if (gnome_vfs_get_file_info (uri,
2360 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2362 mime_type = gnome_vfs_file_info_get_mime_type (info);
2363 mime_part = tny_platform_factory_new_mime_part
2364 (modest_runtime_get_platform_factory ());
2366 /* try to get the attachment's size; this may fail for weird
2367 * file systems, like obex, upnp... */
2368 if (allowed_size != 0 &&
2369 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2371 if (size > allowed_size) {
2372 modest_platform_information_banner (NULL, NULL,
2373 dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2377 g_warning ("%s: could not get attachment size", __FUNCTION__);
2379 stream = create_stream_for_uri (uri);
2381 if (stream == NULL) {
2383 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2385 g_object_unref (mime_part);
2386 gnome_vfs_file_info_unref (info);
2390 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2391 g_object_unref (stream);
2393 content_id = g_strdup_printf ("%d", priv->next_cid);
2394 tny_mime_part_set_content_id (mime_part, content_id);
2395 g_free (content_id);
2398 basename = g_path_get_basename (filename);
2399 tny_mime_part_set_filename (mime_part, basename);
2402 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2403 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2405 info->size == 0, info->size);
2406 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2407 gtk_widget_show_all (priv->attachments_caption);
2408 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2410 g_object_unref (mime_part);
2411 gnome_vfs_file_info_unref (info);
2418 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2421 ModestMsgEditWindowPrivate *priv;
2424 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2425 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2427 if (att_list == NULL) {
2428 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2430 g_object_ref (att_list);
2433 if (tny_list_get_length (att_list) == 0) {
2434 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2436 gboolean dialog_response;
2437 gchar *message = NULL;
2438 gchar *filename = NULL;
2440 if (tny_list_get_length (att_list) == 1) {
2442 iter = tny_list_create_iterator (att_list);
2443 part = (TnyMimePart *) tny_iterator_get_current (iter);
2444 g_object_unref (iter);
2445 if (TNY_IS_MSG (part)) {
2446 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2448 filename = tny_header_dup_subject (header);
2449 g_object_unref (header);
2451 if (filename == NULL) {
2452 filename = g_strdup (_("mail_va_no_subject"));
2455 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2457 g_object_unref (part);
2459 filename = g_strdup ("");
2461 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2462 tny_list_get_length (att_list)), filename);
2465 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2468 if (dialog_response != GTK_RESPONSE_OK) {
2469 g_object_unref (att_list);
2472 hildon_banner_show_information (NULL, NULL, _("mcen_me_inbox_remove_attachments"));
2474 for (iter = tny_list_create_iterator (att_list);
2475 !tny_iterator_is_done (iter);
2476 tny_iterator_next (iter)) {
2477 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2478 const gchar *att_id;
2479 tny_list_remove (priv->attachments, (GObject *) mime_part);
2481 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2483 if (tny_list_get_length (priv->attachments) == 0)
2484 gtk_widget_hide (priv->attachments_caption);
2485 att_id = tny_mime_part_get_content_id (mime_part);
2487 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2489 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2490 g_object_unref (mime_part);
2492 g_object_unref (iter);
2495 g_object_unref (att_list);
2497 /* if the last attachment has been removed, focus the Subject: field */
2498 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2499 gtk_widget_grab_focus (priv->subject_field);
2503 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2506 ModestMsgEditWindowPrivate *priv;
2507 GdkColor *new_color;
2508 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2510 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2511 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2514 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2516 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2518 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2520 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2525 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2528 ModestMsgEditWindowPrivate *priv;
2529 gint new_size_index;
2530 ModestMsgEditWindow *window;
2533 window = MODEST_MSG_EDIT_WINDOW (userdata);
2534 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2535 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2537 if (gtk_check_menu_item_get_active (menu_item)) {
2539 WPTextBufferFormat format;
2541 memset (&format, 0, sizeof (format));
2542 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2544 label = gtk_bin_get_child (GTK_BIN (menu_item));
2546 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2547 format.cs.font_size = TRUE;
2548 format.cs.text_position = TRUE;
2549 format.cs.font = TRUE;
2550 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2551 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2553 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2554 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2555 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2557 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2558 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2559 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2565 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2568 ModestMsgEditWindowPrivate *priv;
2569 gint new_font_index;
2570 ModestMsgEditWindow *window;
2573 window = MODEST_MSG_EDIT_WINDOW (userdata);
2574 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2575 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2577 if (gtk_check_menu_item_get_active (menu_item)) {
2580 label = gtk_bin_get_child (GTK_BIN (menu_item));
2582 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2584 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2585 GINT_TO_POINTER(new_font_index)))
2586 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2588 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2589 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2590 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2596 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2599 ModestMsgEditWindowPrivate *priv = NULL;
2600 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2602 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2603 if (!priv->update_caption_visibility)
2606 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2608 gtk_widget_show (priv->cc_caption);
2610 gtk_widget_hide (priv->cc_caption);
2612 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2616 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2619 ModestMsgEditWindowPrivate *priv = NULL;
2620 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2622 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2623 if (!priv->update_caption_visibility)
2626 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2628 gtk_widget_show (priv->bcc_caption);
2630 gtk_widget_hide (priv->bcc_caption);
2632 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2636 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2637 ModestRecptEditor *editor)
2639 ModestMsgEditWindowPrivate *priv;
2641 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2642 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2644 /* we check for low-mem; in that case, show a warning, and don't allow
2645 * for the addressbook
2647 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2650 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2652 if (editor == NULL) {
2653 GtkWidget *view_focus;
2654 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2656 /* This code should be kept in sync with ModestRecptEditor. The
2657 textview inside the recpt editor is the one that really gets the
2658 focus. As it's inside a scrolled window, and this one inside the
2659 hbox recpt editor inherits from, we'll need to go up in the
2660 hierarchy to know if the text view is part of the recpt editor
2661 or if it's a different text entry */
2663 if (gtk_widget_get_parent (view_focus)) {
2664 GtkWidget *first_parent;
2666 first_parent = gtk_widget_get_parent (view_focus);
2667 if (gtk_widget_get_parent (first_parent) &&
2668 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2669 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2674 editor = MODEST_RECPT_EDITOR (priv->to_field);
2678 modest_address_book_select_addresses (editor);
2683 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2685 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2687 modest_msg_edit_window_open_addressbook (window, NULL);
2691 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2692 gboolean show_toolbar)
2694 ModestWindowPrivate *parent_priv;
2696 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2697 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2699 /* We can not just use the code of
2700 modest_msg_edit_window_setup_toolbar because it has a
2701 mixture of both initialization and creation code. */
2703 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2705 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2709 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2710 TnyHeaderFlags priority_flags)
2712 ModestMsgEditWindowPrivate *priv;
2713 ModestWindowPrivate *parent_priv;
2715 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2717 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2718 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2720 if (priv->priority_flags != priority_flags) {
2721 GtkAction *priority_action = NULL;
2723 priv->priority_flags = priority_flags;
2725 switch (priority_flags) {
2726 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2727 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2728 MODEST_HEADER_ICON_HIGH,
2729 HILDON_ICON_SIZE_XSMALL);
2730 gtk_widget_show (priv->priority_icon);
2731 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2732 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2734 case TNY_HEADER_FLAG_LOW_PRIORITY:
2735 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2736 MODEST_HEADER_ICON_LOW,
2737 HILDON_ICON_SIZE_XSMALL);
2738 gtk_widget_show (priv->priority_icon);
2739 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2740 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2743 gtk_widget_hide (priv->priority_icon);
2744 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2745 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2748 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2749 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2754 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2757 ModestMsgEditWindowPrivate *priv;
2758 ModestWindowPrivate *parent_priv;
2759 gint current_format;
2761 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2763 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2764 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2766 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2767 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2769 if (current_format != file_format) {
2770 switch (file_format) {
2771 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2772 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2773 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2775 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2779 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2780 response = gtk_dialog_run (GTK_DIALOG (dialog));
2781 gtk_widget_destroy (dialog);
2782 if (response == GTK_RESPONSE_OK) {
2783 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2785 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
2786 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2791 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2792 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2793 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2798 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2801 ModestMsgEditWindowPrivate *priv;
2802 WPTextBufferFormat oldfmt, fmt;
2803 gint old_position = 0;
2807 GdkColor *color = NULL;
2808 gboolean bold, bold_set, italic, italic_set;
2809 gboolean underline, underline_set;
2810 gboolean strikethrough, strikethrough_set;
2811 gboolean position_set;
2812 gboolean font_size_set, font_set, color_set;
2815 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2816 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2818 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2819 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2820 GTK_WINDOW(dialog), GTK_WINDOW (window));
2822 /* First we get the currently selected font information */
2823 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2825 switch (oldfmt.text_position) {
2826 case TEXT_POSITION_NORMAL:
2829 case TEXT_POSITION_SUPERSCRIPT:
2837 g_object_set (G_OBJECT (dialog),
2838 "bold", oldfmt.bold != FALSE,
2839 "bold-set", !oldfmt.cs.bold,
2840 "underline", oldfmt.underline != FALSE,
2841 "underline-set", !oldfmt.cs.underline,
2842 "italic", oldfmt.italic != FALSE,
2843 "italic-set", !oldfmt.cs.italic,
2844 "strikethrough", oldfmt.strikethrough != FALSE,
2845 "strikethrough-set", !oldfmt.cs.strikethrough,
2846 "color", &oldfmt.color,
2847 "color-set", !oldfmt.cs.color,
2848 "size", wp_font_size[oldfmt.font_size],
2849 "size-set", !oldfmt.cs.font_size,
2850 "position", old_position,
2851 "position-set", !oldfmt.cs.text_position,
2852 "family", wp_get_font_name (oldfmt.font),
2853 "family-set", !oldfmt.cs.font,
2856 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2857 GTK_WINDOW (dialog), GTK_WINDOW (window));
2858 gtk_widget_show_all (dialog);
2859 priv->font_dialog = dialog;
2860 response = gtk_dialog_run (GTK_DIALOG (dialog));
2861 priv->font_dialog = NULL;
2862 if (response == GTK_RESPONSE_OK) {
2864 g_object_get( dialog,
2866 "bold-set", &bold_set,
2867 "underline", &underline,
2868 "underline-set", &underline_set,
2870 "italic-set", &italic_set,
2871 "strikethrough", &strikethrough,
2872 "strikethrough-set", &strikethrough_set,
2874 "color-set", &color_set,
2876 "size-set", &font_size_set,
2877 "family", &font_name,
2878 "family-set", &font_set,
2879 "position", &position,
2880 "position-set", &position_set,
2885 if (response == GTK_RESPONSE_OK) {
2886 memset(&fmt, 0, sizeof(fmt));
2892 fmt.italic = italic;
2893 fmt.cs.italic = TRUE;
2895 if (underline_set) {
2896 fmt.underline = underline;
2897 fmt.cs.underline = TRUE;
2899 if (strikethrough_set) {
2900 fmt.strikethrough = strikethrough;
2901 fmt.cs.strikethrough = TRUE;
2906 ? TEXT_POSITION_NORMAL
2907 : ( ( position == 1 )
2908 ? TEXT_POSITION_SUPERSCRIPT
2909 : TEXT_POSITION_SUBSCRIPT );
2910 fmt.cs.text_position = TRUE;
2911 fmt.font_size = oldfmt.font_size;
2915 fmt.cs.color = TRUE;
2918 fmt.font = wp_get_font_index(font_name,
2923 if (font_size_set) {
2924 fmt.cs.font_size = TRUE;
2925 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2927 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2928 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2930 gtk_widget_destroy (dialog);
2932 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2936 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2938 ModestMsgEditWindowPrivate *priv;
2940 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2941 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2943 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2945 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2946 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2950 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2952 ModestMsgEditWindowPrivate *priv;
2954 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2955 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2957 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2959 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2960 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2965 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2967 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2969 priv->can_undo = can_undo;
2973 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2975 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2977 priv->can_redo = can_redo;
2981 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2983 ModestMsgEditWindowPrivate *priv;
2984 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2985 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2987 return priv->can_undo;
2991 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2993 ModestMsgEditWindowPrivate *priv;
2994 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2995 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2997 return priv->can_redo;
3002 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3005 GtkTextIter match_start, match_end;
3007 if (image_id == NULL)
3010 gtk_text_buffer_get_start_iter (buffer, &iter);
3012 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3013 GSList *tags = gtk_text_iter_get_tags (&match_start);
3015 for (node = tags; node != NULL; node = g_slist_next (node)) {
3016 GtkTextTag *tag = (GtkTextTag *) node->data;
3017 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3018 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3019 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3021 offset = gtk_text_iter_get_offset (&match_start);
3022 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3023 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3027 gtk_text_iter_forward_char (&iter);
3032 message_is_empty (ModestMsgEditWindow *window)
3034 ModestMsgEditWindowPrivate *priv = NULL;
3036 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3037 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3039 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3040 * so we can ignore markup.
3042 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3045 count = gtk_text_buffer_get_char_count (buf);
3051 msg_body_focus (GtkWidget *focus,
3052 GdkEventFocus *event,
3056 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3057 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3058 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3063 recpt_field_changed (GtkTextBuffer *buffer,
3064 ModestMsgEditWindow *editor)
3066 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3067 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3071 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3073 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3074 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3078 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3081 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3082 GtkTextBuffer *buffer;
3084 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3085 gtk_text_buffer_set_modified (buffer, modified);
3086 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3087 gtk_text_buffer_set_modified (buffer, modified);
3088 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3089 gtk_text_buffer_set_modified (buffer, modified);
3090 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3094 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3096 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3097 const char *account_name;
3098 GtkTextBuffer *buffer;
3100 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3101 if (gtk_text_buffer_get_modified (buffer))
3103 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3104 if (gtk_text_buffer_get_modified (buffer))
3106 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3107 if (gtk_text_buffer_get_modified (buffer))
3109 if (gtk_text_buffer_get_modified (priv->text_buffer))
3111 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3112 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3123 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3125 ModestMsgEditWindowPrivate *priv = NULL;
3127 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3128 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3130 /* check if there's no recipient added */
3131 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3132 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3133 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3134 /* no recipient contents, then select contacts */
3135 modest_msg_edit_window_open_addressbook (window, NULL);
3139 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3140 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3143 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3144 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3147 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3148 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3152 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3153 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3154 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3161 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3162 ModestMsgEditWindow *window)
3164 modest_msg_edit_window_offer_attach_file (window);
3168 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3170 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3172 return priv->clipboard_text;
3176 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3178 ModestMsgEditWindow *window)
3180 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3181 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3183 if (!GTK_WIDGET_VISIBLE (window))
3186 g_object_ref (window);
3187 text = gtk_clipboard_wait_for_text (selection_clipboard);
3189 if (priv->clipboard_text != NULL) {
3190 g_free (priv->clipboard_text);
3192 priv->clipboard_text = text;
3194 if (GTK_WIDGET_VISIBLE (window)) {
3195 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3197 g_object_unref (window);
3200 static gboolean clipboard_owner_change_idle (gpointer userdata)
3202 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3203 ModestMsgEditWindowPrivate *priv;
3205 gdk_threads_enter ();
3206 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3207 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3209 priv->clipboard_owner_idle = 0;
3210 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3211 gdk_threads_leave ();
3217 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3219 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3220 if (priv->clipboard_owner_idle == 0) {
3221 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3226 subject_field_move_cursor (GtkEntry *entry,
3227 GtkMovementStep step,
3232 if (!GTK_WIDGET_VISIBLE (window))
3235 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3239 update_window_title (ModestMsgEditWindow *window)
3241 ModestMsgEditWindowPrivate *priv = NULL;
3242 const gchar *subject;
3244 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3245 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3246 if (subject == NULL || subject[0] == '\0')
3247 subject = _("mail_va_new_email");
3249 gtk_window_set_title (GTK_WINDOW (window), subject);
3254 subject_field_changed (GtkEditable *editable,
3255 ModestMsgEditWindow *window)
3257 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3258 update_window_title (window);
3259 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3260 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3261 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3265 subject_field_insert_text (GtkEditable *editable,
3267 gint new_text_length,
3269 ModestMsgEditWindow *window)
3271 GString *result = g_string_new ("");
3273 gint result_len = 0;
3274 const gchar *entry_text = NULL;
3277 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3278 old_length = g_utf8_strlen (entry_text, -1);
3280 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3281 gunichar c = g_utf8_get_char_validated (current, 8);
3282 /* Invalid unichar, stop */
3288 result = g_string_append_unichar (result, c);
3292 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3293 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3296 /* Prevent endless recursion */
3297 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3298 g_signal_emit_by_name (editable, "insert-text",
3299 (gpointer) result->str, (gpointer) result->len,
3300 (gpointer) position, (gpointer) window);
3301 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3305 if (result_len + old_length > 1000) {
3306 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3307 dgettext("hildon-common-strings",
3308 "ckdg_ib_maximum_characters_reached"));
3311 g_string_free (result, TRUE);
3315 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3318 ModestMsgEditWindowPrivate *priv = NULL;
3320 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3321 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3323 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3326 gtk_widget_show_all (priv->find_toolbar);
3327 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3329 gtk_widget_hide_all (priv->find_toolbar);
3330 gtk_widget_grab_focus (priv->msg_body);
3336 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3338 GtkTextIter *match_start,
3339 GtkTextIter *match_end)
3341 GtkTextIter end_iter;
3342 gchar *str_casefold;
3345 gchar *range_casefold;
3348 gboolean result = FALSE;
3355 gtk_text_iter_forward_to_end (&end_iter);
3357 str_casefold = g_utf8_casefold (str, -1);
3358 str_chars_n = strlen (str);
3360 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3361 range_casefold = g_utf8_casefold (range_text, -1);
3362 range_chars_n = strlen (range_casefold);
3364 if (range_chars_n < str_chars_n) {
3365 g_free (str_casefold);
3366 g_free (range_text);
3367 g_free (range_casefold);
3371 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3372 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3373 if (!g_utf8_collate (range_subtext, str_casefold)) {
3374 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3376 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3377 match_start, match_end, NULL);
3378 g_free (found_text);
3380 g_free (range_subtext);
3384 g_free (str_casefold);
3385 g_free (range_text);
3386 g_free (range_casefold);
3393 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3394 ModestMsgEditWindow *window)
3396 gchar *current_search = NULL;
3397 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3399 GtkTextIter selection_start, selection_end;
3400 GtkTextIter match_start, match_end;
3401 gboolean continue_search = FALSE;
3403 if (message_is_empty (window)) {
3404 g_free (priv->last_search);
3405 priv->last_search = NULL;
3406 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3410 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3411 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3412 g_free (current_search);
3413 g_free (priv->last_search);
3414 priv->last_search = NULL;
3415 /* Information banner about empty search */
3416 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3420 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3421 continue_search = TRUE;
3423 g_free (priv->last_search);
3424 priv->last_search = g_strdup (current_search);
3427 if (continue_search) {
3428 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3429 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3430 &match_start, &match_end);
3432 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3434 GtkTextIter buffer_start;
3435 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3436 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3437 &match_start, &match_end);
3439 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3442 /* Mark as selected the string found in search */
3444 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3445 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3446 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3448 g_free (priv->last_search);
3449 priv->last_search = NULL;
3451 g_free (current_search);
3455 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3456 ModestMsgEditWindow *window)
3458 GtkToggleAction *toggle;
3459 ModestWindowPrivate *parent_priv;
3460 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3462 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3463 gtk_toggle_action_set_active (toggle, FALSE);
3467 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3469 ModestMsgEditWindowPrivate *priv;
3471 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3476 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3479 ModestMsgEditWindowPrivate *priv;
3481 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3487 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3490 ModestMsgEditWindowPrivate *priv;
3491 TnyHeader *header = NULL;
3493 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3494 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3496 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3497 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3499 if (priv->draft_msg != NULL) {
3500 g_object_unref (priv->draft_msg);
3503 if (draft != NULL) {
3504 g_object_ref (draft);
3505 header = tny_msg_get_header (draft);
3506 if (priv->msg_uid) {
3507 g_free (priv->msg_uid);
3508 priv->msg_uid = NULL;
3510 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3511 if (GTK_WIDGET_REALIZED (window)) {
3512 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3513 gtk_widget_destroy (GTK_WIDGET (window));
3519 priv->draft_msg = draft;
3523 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3524 GtkTextIter *start, GtkTextIter *end,
3527 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3528 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3531 if (tag == NULL) return;
3532 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3533 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3534 replace_with_images (window, priv->images);
3539 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3542 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3544 g_return_if_fail (TNY_IS_MIME_PART (part));
3545 tny_list_prepend (priv->attachments, (GObject *) part);
3546 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3547 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3548 gtk_widget_show_all (priv->attachments_caption);
3549 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3553 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3555 ModestMsgEditWindowPrivate *priv;
3557 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3558 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3560 return priv->msg_uid;
3564 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3565 ModestMsgEditWindowWidgetType widget_type)
3567 ModestMsgEditWindowPrivate *priv;
3569 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3570 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3572 switch (widget_type) {
3573 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3574 return priv->msg_body;
3576 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3577 return priv->to_field;
3579 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3580 return priv->cc_field;
3582 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3583 return priv->bcc_field;
3585 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3586 return priv->subject_field;
3588 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3589 return priv->attachments_view;
3597 remove_tags (WPTextBuffer *buffer)
3599 GtkTextIter start, end;
3601 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3602 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3604 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3608 on_account_removed (TnyAccountStore *account_store,
3609 TnyAccount *account,
3612 /* Do nothing if it's a store account, because we use the
3613 transport to send the messages */
3614 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3615 const gchar *parent_acc = NULL;
3616 const gchar *our_acc = NULL;
3618 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3619 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3620 /* Close this window if I'm showing a message of the removed account */
3621 if (strcmp (parent_acc, our_acc) == 0)
3622 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3627 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3629 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3631 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3637 set_zoom_do_nothing (ModestWindow *window,
3643 get_zoom_do_nothing (ModestWindow *window)
3648 typedef struct _MessageSettingsHelper {
3649 ModestMsgEditWindow *window;
3650 GSList *priority_group;
3651 GtkWidget *align_picker;
3652 } MessageSettingsHelper;
3655 on_priority_toggle (HildonCheckButton *button,
3656 MessageSettingsHelper *helper)
3659 ModestMsgEditWindowPrivate *priv;
3661 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3662 if (hildon_check_button_get_active (button)) {
3664 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3665 HildonCheckButton *node_button = (HildonCheckButton *) node->data;
3666 if ((node_button != button) &&
3667 hildon_check_button_get_active (node_button)) {
3668 hildon_check_button_set_active (node_button, FALSE);
3670 if (priv->priority_flags != (TnyHeaderFlags) g_object_get_data (G_OBJECT (button), "priority"))
3671 modest_msg_edit_window_set_priority_flags (helper->window,
3673 g_object_get_data (G_OBJECT (button),
3679 gboolean found = FALSE;
3680 /* If no one is active, activate it again */
3681 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3682 HildonCheckButton *node_button = (HildonCheckButton *) node->data;
3683 if (hildon_check_button_get_active (node_button)) {
3689 hildon_check_button_set_active (button, TRUE);
3695 on_format_picker_value_changed (HildonPickerButton *button,
3696 MessageSettingsHelper *helper)
3698 ModestMsgEditFormat new_format, old_format;
3701 switch (hildon_picker_button_get_active (button)) {
3703 new_format = MODEST_MSG_EDIT_FORMAT_HTML;
3704 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
3708 new_format = MODEST_MSG_EDIT_FORMAT_TEXT;
3709 file_format = MODEST_FILE_FORMAT_PLAIN_TEXT;
3713 old_format = modest_msg_edit_window_get_format (helper->window);
3714 if (new_format != old_format) {
3715 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (helper->window), file_format);
3717 switch (modest_msg_edit_window_get_format (helper->window)) {
3718 case MODEST_MSG_EDIT_FORMAT_TEXT:
3719 hildon_picker_button_set_active (button, 0);
3720 gtk_widget_set_sensitive (helper->align_picker, FALSE);
3722 case MODEST_MSG_EDIT_FORMAT_HTML:
3724 hildon_picker_button_set_active (button, 1);
3725 gtk_widget_set_sensitive (helper->align_picker, TRUE);
3732 on_align_picker_value_changed (HildonPickerButton *button,
3733 MessageSettingsHelper *helper)
3735 GtkJustification new_justify;
3736 ModestMsgEditFormatState *format_state = NULL;
3738 switch (hildon_picker_button_get_active (button)) {
3740 new_justify = GTK_JUSTIFY_CENTER;
3743 new_justify = GTK_JUSTIFY_RIGHT;
3747 new_justify = GTK_JUSTIFY_LEFT;
3751 format_state = modest_msg_edit_window_get_format_state (helper->window);
3752 if (format_state->justification != new_justify)
3753 format_state->justification = new_justify;
3754 modest_msg_edit_window_set_format_state (helper->window, format_state);
3755 g_free (format_state);
3759 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
3763 GtkWidget *priority_hbox;
3764 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
3765 GtkWidget *captioned;
3766 GtkSizeGroup *title_sizegroup, *value_sizegroup;
3767 GtkWidget *format_picker;
3768 GtkWidget *format_selector;
3769 GtkWidget *align_selector;
3770 ModestMsgEditWindowPrivate *priv;
3771 MessageSettingsHelper helper = {0,};
3772 ModestMsgEditFormatState *format_state = NULL;
3774 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3775 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3776 helper.window = window;
3777 helper.priority_group = NULL;
3779 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3780 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3782 dialog = gtk_dialog_new ();
3783 vbox = gtk_vbox_new (FALSE, 0);
3784 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
3785 gtk_widget_show (vbox);
3787 /* Priority toggles */
3788 priority_hbox = gtk_hbox_new (TRUE, 0);
3789 high_toggle = hildon_check_button_new (HILDON_SIZE_FINGER_HEIGHT);
3790 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
3791 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
3792 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
3793 medium_toggle = hildon_check_button_new (HILDON_SIZE_FINGER_HEIGHT);
3794 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
3795 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
3796 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
3797 low_toggle = hildon_check_button_new (HILDON_SIZE_FINGER_HEIGHT);
3798 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
3799 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
3800 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
3801 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, FALSE, FALSE, 0);
3802 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, FALSE, FALSE, 0);
3803 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, FALSE, FALSE, 0);
3804 gtk_widget_show_all (priority_hbox);
3805 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
3806 _("mcen_me_editor_message_priority"), priority_hbox);
3807 gtk_widget_show (captioned);
3808 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
3810 /* format selector */
3811 format_selector = hildon_touch_selector_new_text ();
3812 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (format_selector), _("mcen_me_editor_plain_text"));
3813 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (format_selector), _("mcen_me_editor_formatted_text"));
3814 format_picker = hildon_picker_button_new (MODEST_EDITABLE_SIZE,
3815 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
3816 hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (format_picker), HILDON_TOUCH_SELECTOR (format_selector));
3817 modest_maemo_utils_set_hbutton_layout (title_sizegroup, value_sizegroup,
3818 _("mcen_me_editor_format"), format_picker);
3819 gtk_widget_show_all (format_picker);
3820 gtk_box_pack_start (GTK_BOX (vbox), format_picker, FALSE, FALSE, 0);
3822 /* alignment selector */
3823 align_selector = hildon_touch_selector_new_text ();
3824 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (align_selector), _("mcen_me_editor_align_left"));
3825 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (align_selector), _("mcen_me_editor_align_centred"));
3826 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (align_selector), _("mcen_me_editor_align_right"));
3827 helper.align_picker = hildon_picker_button_new (MODEST_EDITABLE_SIZE,
3828 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
3829 hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (helper.align_picker), HILDON_TOUCH_SELECTOR (align_selector));
3830 modest_maemo_utils_set_hbutton_layout (title_sizegroup, value_sizegroup,
3831 _("mcen_me_editor_align"), helper.align_picker);
3832 gtk_widget_show_all (helper.align_picker);
3833 gtk_box_pack_start (GTK_BOX (vbox), helper.align_picker, FALSE, FALSE, 0);
3835 g_object_unref (title_sizegroup);
3836 g_object_unref (value_sizegroup);
3837 gtk_window_set_title (GTK_WINDOW (dialog), _("TODO: Message settings"));
3839 /* Set current values */
3840 switch (priv->priority_flags) {
3841 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3842 hildon_check_button_set_active (HILDON_CHECK_BUTTON (high_toggle), TRUE);
3844 case TNY_HEADER_FLAG_LOW_PRIORITY:
3845 hildon_check_button_set_active (HILDON_CHECK_BUTTON (low_toggle), TRUE);
3848 hildon_check_button_set_active (HILDON_CHECK_BUTTON (medium_toggle), TRUE);
3852 switch (modest_msg_edit_window_get_format (window)) {
3853 case MODEST_MSG_EDIT_FORMAT_TEXT:
3854 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (format_picker), 0);
3855 gtk_widget_set_sensitive (helper.align_picker, FALSE);
3857 case MODEST_MSG_EDIT_FORMAT_HTML:
3859 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (format_picker), 1);
3860 gtk_widget_set_sensitive (helper.align_picker, TRUE);
3864 format_state = modest_msg_edit_window_get_format_state (window);
3865 switch (format_state->justification) {
3866 case GTK_JUSTIFY_RIGHT:
3867 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 2);
3869 case GTK_JUSTIFY_CENTER:
3870 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 1);
3873 hildon_picker_button_set_active (HILDON_PICKER_BUTTON (helper.align_picker), 0);
3877 g_free (format_state);
3879 /* Signal connects */
3880 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3881 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3882 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
3883 g_signal_connect (G_OBJECT (format_picker), "value-changed", G_CALLBACK (on_format_picker_value_changed), &helper);
3884 g_signal_connect (G_OBJECT (helper.align_picker), "value-changed",
3885 G_CALLBACK (on_align_picker_value_changed), &helper);
3887 gtk_dialog_run (GTK_DIALOG (dialog));
3889 /* Read new values */
3891 gtk_widget_destroy (dialog);
3892 g_slist_free (helper.priority_group);
3896 static void on_message_settings (GtkAction *action,
3897 ModestMsgEditWindow *window)
3899 modest_msg_edit_window_show_msg_settings_dialog (window);
3903 static void add_button_to_menu (ModestMsgEditWindow *self,
3904 HildonAppMenu *menu,
3906 ModestDimmingRulesGroup *group,
3907 GCallback dimming_callback)
3909 if (dimming_callback)
3910 modest_dimming_rules_group_add_widget_rule (group,
3911 GTK_WIDGET (button),
3913 MODEST_WINDOW (self));
3914 hildon_app_menu_append (menu, GTK_BUTTON (button));
3917 static void add_to_menu (ModestMsgEditWindow *self,
3918 HildonAppMenu *menu,
3921 ModestDimmingRulesGroup *group,
3922 GCallback dimming_callback)
3926 button = gtk_button_new_with_label (label);
3927 g_signal_connect_after (G_OBJECT (button), "clicked",
3928 callback, (gpointer) self);
3929 add_button_to_menu (self, menu, GTK_BUTTON (button), group, dimming_callback);
3933 setup_menu (ModestMsgEditWindow *self, ModestDimmingRulesGroup *group)
3935 ModestMsgEditWindowPrivate *priv = NULL;
3937 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
3939 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3941 priv->app_menu = hildon_app_menu_new ();
3943 /* Settings menu buttons */
3944 add_to_menu (self, HILDON_APP_MENU (priv->app_menu), _("mcen_me_editor_checknames"),
3945 G_CALLBACK (modest_ui_actions_on_check_names),
3947 add_to_menu (self, HILDON_APP_MENU (priv->app_menu), _("mcen_me_inbox_undo"),
3948 G_CALLBACK (modest_ui_actions_on_undo),
3951 priv->cc_button = hildon_check_button_new (0);
3952 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("TODO: Show CC"));
3953 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
3955 add_button_to_menu (self, HILDON_APP_MENU (priv->app_menu), GTK_BUTTON (priv->cc_button),
3957 priv->bcc_button = hildon_check_button_new (0);
3958 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("TODO: Show BCC"));
3959 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
3961 add_button_to_menu (self, HILDON_APP_MENU (priv->app_menu), GTK_BUTTON (priv->bcc_button),
3964 add_to_menu (self, HILDON_APP_MENU (priv->app_menu), _("mcen_me_editor_attach_inlineimage"),
3965 G_CALLBACK (modest_ui_actions_on_insert_image),
3967 add_to_menu (self, HILDON_APP_MENU (priv->app_menu), _("mcen_me_inbox_remove_attachments"),
3968 G_CALLBACK (modest_ui_actions_on_remove_attachments),
3970 add_to_menu (self, HILDON_APP_MENU (priv->app_menu), _("TODO: Message settings..."),
3971 G_CALLBACK (on_message_settings),
3974 /* TODO: find in toolbar check button */
3976 hildon_stackable_window_set_main_menu (HILDON_STACKABLE_WINDOW (self),
3977 HILDON_APP_MENU (priv->app_menu));
3981 modest_msg_edit_window_toggle_menu (HildonWindow *window,
3985 ModestMsgEditWindowPrivate *priv = NULL;
3987 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3989 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3991 gtk_widget_queue_resize (priv->app_menu);
3993 return HILDON_WINDOW_CLASS (parent_class)->toggle_menu (window, button, time);