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 "modest-scroll-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"
83 #define DEFAULT_FONT_SIZE 3
84 #define DEFAULT_FONT 2
85 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
86 #define DEFAULT_MAIN_VBOX_SPACING 6
87 #define SUBJECT_MAX_LENGTH 1000
88 #define IMAGE_MAX_WIDTH 560
89 #define DEFAULT_FONT_SCALE 1.5
91 static gboolean is_wp_text_buffer_started = FALSE;
93 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
94 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
95 static void modest_msg_edit_window_finalize (GObject *obj);
97 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
98 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
99 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
101 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
102 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
103 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
104 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
105 GtkTextIter *start, GtkTextIter *end,
107 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
108 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
109 static void subject_field_insert_text (GtkEditable *editable,
111 gint new_text_length,
113 ModestMsgEditWindow *window);
114 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
116 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
118 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
120 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
121 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
122 GdkEventWindowState *event,
124 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
125 ModestRecptEditor *editor);
126 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
127 ModestMsgEditWindow *window);
129 /* ModestWindow methods implementation */
130 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
131 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
132 gboolean show_toolbar);
133 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
135 ModestMsgEditWindow *window);
136 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
137 static void subject_field_move_cursor (GtkEntry *entry,
138 GtkMovementStep step,
142 static void update_window_title (ModestMsgEditWindow *window);
145 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
146 ModestMsgEditWindow *window);
147 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
148 ModestMsgEditWindow *window);
149 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
151 GtkTextIter *match_start,
152 GtkTextIter *match_end);
154 static void remove_tags (WPTextBuffer *buffer);
156 static void on_account_removed (TnyAccountStore *account_store,
160 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
161 static void set_zoom_do_nothing (ModestWindow *window, gdouble zoom);
162 static gdouble get_zoom_do_nothing (ModestWindow *window);
164 static void init_window (ModestMsgEditWindow *obj);
166 gboolean scroll_drag_timeout (gpointer userdata);
167 static void correct_scroll (ModestMsgEditWindow *w);
168 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
169 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
170 ModestMsgEditWindow *userdata);
171 static void text_buffer_mark_set (GtkTextBuffer *buffer,
174 ModestMsgEditWindow *userdata);
175 static void vadj_changed (GtkAdjustment *adj,
176 ModestMsgEditWindow *window);
178 static void DEBUG_BUFFER (WPTextBuffer *buffer)
182 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
184 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
185 while (!gtk_text_iter_is_end (&iter)) {
186 GString *output = g_string_new ("");
187 GSList *toggled_tags;
190 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
191 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
192 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
193 GtkTextTag *tag = (GtkTextTag *) node->data;
195 g_object_get (G_OBJECT (tag), "name", &name, NULL);
196 output = g_string_append (output, name);
197 g_string_append (output, " ");
199 output = g_string_append (output, "] OPENED [ ");
200 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
201 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
202 GtkTextTag *tag = (GtkTextTag *) node->data;
204 g_object_get (G_OBJECT (tag), "name", &name, NULL);
205 output = g_string_append (output, name);
206 g_string_append (output, " ");
208 output = g_string_append (output, "]\n");
209 g_message ("%s", output->str);
210 g_string_free (output, TRUE);
211 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
213 g_message ("END BUFFER");
218 /* static gboolean */
219 /* on_key_pressed (GtkWidget *self, */
220 /* GdkEventKey *event, */
221 /* gpointer user_data); */
223 /* list my signals */
230 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
231 struct _ModestMsgEditWindowPrivate {
234 GtkWidget *header_box;
236 ModestPairList *from_field_protos;
237 GtkWidget *from_field;
238 gchar *original_account_name;
242 GtkWidget *bcc_field;
243 GtkWidget *subject_field;
244 GtkWidget *attachments_view;
245 GtkWidget *priority_icon;
246 GtkWidget *add_attachment_button;
248 GtkWidget *cc_caption;
249 GtkWidget *bcc_caption;
250 gboolean update_caption_visibility;
251 GtkWidget *attachments_caption;
253 GtkTextBuffer *text_buffer;
255 GtkWidget *font_size_toolitem;
256 GtkWidget *font_face_toolitem;
257 GtkWidget *font_color_button;
258 GSList *font_items_group;
259 GtkWidget *font_tool_button_label;
260 GSList *size_items_group;
261 GtkWidget *size_tool_button_label;
263 GtkWidget *find_toolbar;
266 GtkWidget *font_dialog;
269 guint scroll_drag_timeout_id;
273 TnyList *attachments;
278 TnyHeaderFlags priority_flags;
280 gboolean can_undo, can_redo;
281 gulong clipboard_change_handler_id;
282 gulong default_clipboard_change_handler_id;
283 gulong account_removed_handler_id;
284 guint clipboard_owner_idle;
285 gchar *clipboard_text;
294 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
295 MODEST_TYPE_MSG_EDIT_WINDOW, \
296 ModestMsgEditWindowPrivate))
298 static GtkWindowClass *parent_class = NULL;
300 /* uncomment the following if you have defined any signals */
301 /* static guint signals[LAST_SIGNAL] = {0}; */
304 modest_msg_edit_window_get_type (void)
306 static GType my_type = 0;
308 static const GTypeInfo my_info = {
309 sizeof(ModestMsgEditWindowClass),
310 NULL, /* base init */
311 NULL, /* base finalize */
312 (GClassInitFunc) modest_msg_edit_window_class_init,
313 NULL, /* class finalize */
314 NULL, /* class data */
315 sizeof(ModestMsgEditWindow),
317 (GInstanceInitFunc) modest_msg_edit_window_init,
320 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
321 "ModestMsgEditWindow",
329 save_state (ModestWindow *self)
331 modest_widget_memory_save (modest_runtime_get_conf(),
332 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
337 restore_settings (ModestMsgEditWindow *self)
339 ModestConf *conf = NULL;
341 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
343 conf = modest_runtime_get_conf ();
344 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
345 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
346 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
347 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL));
348 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
349 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu");
350 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
351 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
353 /* set initial state of cc and bcc */
354 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
355 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
356 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
357 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
358 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
359 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
361 /* Dim at start clipboard actions */
362 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
363 gtk_action_set_sensitive (action, FALSE);
364 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
365 gtk_action_set_sensitive (action, FALSE);
366 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
367 gtk_action_set_sensitive (action, FALSE);
369 modest_widget_memory_restore (conf,
370 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
375 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
377 GObjectClass *gobject_class;
378 ModestWindowClass *modest_window_class;
379 gobject_class = (GObjectClass*) klass;
380 modest_window_class = (ModestWindowClass*) klass;
382 parent_class = g_type_class_peek_parent (klass);
383 gobject_class->finalize = modest_msg_edit_window_finalize;
385 modest_window_class->set_zoom_func = set_zoom_do_nothing;
386 modest_window_class->get_zoom_func = get_zoom_do_nothing;
387 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
388 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
389 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
390 modest_window_class->save_state_func = save_state;
391 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
393 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
397 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
399 ModestMsgEditWindowPrivate *priv;
400 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
402 priv->msg_body = NULL;
404 priv->from_field = NULL;
405 priv->to_field = NULL;
406 priv->cc_field = NULL;
407 priv->bcc_field = NULL;
408 priv->subject_field = NULL;
409 priv->attachments = TNY_LIST (tny_simple_list_new ());
410 priv->images = TNY_LIST (tny_simple_list_new ());
411 priv->images_size = 0;
412 priv->images_count = 0;
415 priv->cc_caption = NULL;
416 priv->bcc_caption = NULL;
417 priv->update_caption_visibility = FALSE;
419 priv->priority_flags = 0;
421 priv->find_toolbar = NULL;
422 priv->last_search = NULL;
424 priv->draft_msg = NULL;
425 priv->outbox_msg = NULL;
426 priv->msg_uid = NULL;
428 priv->can_undo = FALSE;
429 priv->can_redo = FALSE;
430 priv->clipboard_change_handler_id = 0;
431 priv->default_clipboard_change_handler_id = 0;
432 priv->account_removed_handler_id = 0;
433 priv->clipboard_owner_idle = 0;
434 priv->clipboard_text = NULL;
437 priv->scroll_drag_timeout_id = 0;
438 priv->last_upper = 0.0;
440 priv->font_dialog = NULL;
442 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
443 GTK_WINDOW(obj),"applications_email_editor");
445 if (!is_wp_text_buffer_started) {
446 is_wp_text_buffer_started = TRUE;
447 wp_text_buffer_library_init ();
452 hildon_program_add_window (hildon_program_get_instance(),
457 /* FIXME: this is a dup from the one in gtk/ */
460 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
462 static ModestPairList*
463 get_transports (void)
465 GSList *transports = NULL;
467 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
468 GSList *accounts = modest_account_mgr_account_names (account_mgr,
469 TRUE /* only enabled accounts. */);
471 GSList *cursor = accounts;
473 gchar *account_name = cursor->data;
474 gchar *from_string = NULL;
476 from_string = modest_account_mgr_get_from_string (account_mgr,
480 if (from_string && account_name) {
481 gchar *name = account_name;
482 ModestPair *pair = modest_pair_new ((gpointer) name,
483 (gpointer) from_string , TRUE);
484 transports = g_slist_prepend (transports, pair);
487 cursor = cursor->next;
489 g_slist_free (accounts); /* only free the accounts, not the elements,
490 * because they are used in the pairlist */
494 static void window_focus (GtkWindow *window,
498 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
502 scroll_drag_timeout (gpointer userdata)
504 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
505 ModestMsgEditWindowPrivate *priv;
507 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
509 correct_scroll_without_drag_check (win, TRUE);
511 priv->scroll_drag_timeout_id = 0;
517 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
519 ModestMsgEditWindowPrivate *priv;
522 GdkRectangle rectangle;
528 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
530 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
533 insert = gtk_text_buffer_get_insert (priv->text_buffer);
534 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
536 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
537 vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll));
538 offset = priv->msg_body->allocation.y;
540 new_value = vadj->value;
542 if ((offset + rectangle.y + rectangle.height) >
543 ((gint) (vadj->value +vadj->page_size))) {
544 new_value = (offset + rectangle.y) - vadj->page_size * 0.25;
545 if (new_value > vadj->upper - vadj->page_size)
546 new_value = vadj->upper - vadj->page_size;
547 } else if ((offset + rectangle.y) < ((gint) vadj->value)) {
548 new_value = (offset + rectangle.y - vadj->page_size * 0.75);
549 if (((gint) (new_value + vadj->page_size)) < (offset + rectangle.y + rectangle.height))
550 new_value = offset + rectangle.y + rectangle.height - (gint) vadj->page_size;
553 if (new_value > vadj->value)
554 new_value = vadj->value;
557 if (vadj->value != new_value) {
558 g_signal_emit_by_name (GTK_TEXT_VIEW(priv->msg_body)->layout,
560 vadj->value = new_value;
561 gtk_adjustment_value_changed (vadj);
562 /* invalidate body */
563 window = gtk_widget_get_parent_window (priv->msg_body);
565 gdk_window_invalidate_rect (window, NULL, TRUE);
571 correct_scroll (ModestMsgEditWindow *w)
573 ModestMsgEditWindowPrivate *priv;
575 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
576 if (gtk_grab_get_current () == priv->msg_body) {
577 if (priv->scroll_drag_timeout_id == 0) {
578 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
584 correct_scroll_without_drag_check (w, TRUE);
588 text_buffer_end_user_action (GtkTextBuffer *buffer,
589 ModestMsgEditWindow *userdata)
592 correct_scroll (userdata);
596 text_buffer_mark_set (GtkTextBuffer *buffer,
599 ModestMsgEditWindow *userdata)
601 gtk_text_buffer_begin_user_action (buffer);
602 gtk_text_buffer_end_user_action (buffer);
606 cut_clipboard_check (GtkTextView *text_view,
609 GtkTextBuffer *buffer;
611 buffer = gtk_text_view_get_buffer (text_view);
612 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
613 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
618 copy_clipboard_check (GtkTextView *text_view,
621 GtkTextBuffer *buffer;
623 buffer = gtk_text_view_get_buffer (text_view);
624 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
625 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
630 vadj_changed (GtkAdjustment *adj,
631 ModestMsgEditWindow *window)
633 ModestMsgEditWindowPrivate *priv;
635 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
637 if (priv->last_upper != adj->upper) {
638 priv->last_upper = adj->upper;
639 correct_scroll (window);
644 attachment_deleted (ModestAttachmentsView *attachments_view,
647 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
652 connect_signals (ModestMsgEditWindow *obj)
654 ModestMsgEditWindowPrivate *priv;
656 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
658 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
659 G_CALLBACK (text_buffer_refresh_attributes), obj);
660 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
661 G_CALLBACK (text_buffer_can_undo), obj);
662 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
663 G_CALLBACK (text_buffer_can_redo), obj);
664 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
665 G_CALLBACK (body_changed), obj);
666 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
667 G_CALLBACK (body_changed), obj);
668 g_signal_connect (G_OBJECT (obj), "window-state-event",
669 G_CALLBACK (modest_msg_edit_window_window_state_event),
671 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
672 G_CALLBACK (text_buffer_end_user_action), obj);
673 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
674 G_CALLBACK (text_buffer_mark_set), obj);
675 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
676 G_CALLBACK (text_buffer_apply_tag), obj);
677 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
678 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
679 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
680 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
681 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
682 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
684 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
685 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
687 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
688 G_CALLBACK (msg_body_focus), obj);
689 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
690 G_CALLBACK (msg_body_focus), obj);
691 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
692 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
693 "changed", G_CALLBACK (recpt_field_changed), obj);
694 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
695 "changed", G_CALLBACK (recpt_field_changed), obj);
696 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
697 "changed", G_CALLBACK (recpt_field_changed), obj);
698 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
699 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
700 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
702 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
703 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
705 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
707 G_CALLBACK (vadj_changed),
710 priv->clipboard_change_handler_id =
711 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
712 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
713 priv->default_clipboard_change_handler_id =
714 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
715 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
717 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
718 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
719 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
723 init_window (ModestMsgEditWindow *obj)
725 GtkWidget *to_caption, *subject_caption;
726 GtkWidget *main_vbox;
727 ModestMsgEditWindowPrivate *priv;
728 GtkActionGroup *action_group;
729 ModestWindowPrivate *parent_priv;
730 GdkPixbuf *window_icon = NULL;
731 GError *error = NULL;
733 GtkSizeGroup *size_group;
734 GtkWidget *subject_box;
735 GtkWidget *attachment_icon;
736 GtkWidget *window_box;
737 #if (GTK_MINOR_VERSION >= 10)
738 GdkAtom deserialize_type;
740 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
741 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
743 parent_priv->ui_manager = gtk_ui_manager_new();
744 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
745 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
747 /* Add common actions */
748 gtk_action_group_add_actions (action_group,
749 modest_msg_edit_action_entries,
750 G_N_ELEMENTS (modest_msg_edit_action_entries),
752 gtk_action_group_add_toggle_actions (action_group,
753 modest_msg_edit_toggle_action_entries,
754 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
756 gtk_action_group_add_radio_actions (action_group,
757 modest_msg_edit_alignment_radio_action_entries,
758 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
760 G_CALLBACK (modest_ui_actions_on_change_justify),
762 gtk_action_group_add_radio_actions (action_group,
763 modest_msg_edit_priority_action_entries,
764 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
766 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
768 gtk_action_group_add_radio_actions (action_group,
769 modest_msg_edit_file_format_action_entries,
770 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
771 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
772 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
774 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
775 g_object_unref (action_group);
777 /* Load the UI definition */
778 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
781 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
782 g_clear_error (&error);
785 /* Add accelerators */
786 gtk_window_add_accel_group (GTK_WINDOW (obj),
787 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
789 parent_priv->menubar = NULL;
791 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
793 /* Note: This ModestPairList* must exist for as long as the picker
794 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
795 * so it can't know how to manage its memory. */
796 priv->from_field = modest_selector_picker_new (NULL, g_str_equal);
798 priv->to_field = modest_recpt_editor_new ();
799 priv->cc_field = modest_recpt_editor_new ();
800 priv->bcc_field = modest_recpt_editor_new ();
801 subject_box = gtk_hbox_new (FALSE, 0);
802 priv->priority_icon = gtk_image_new ();
803 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
804 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
805 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
806 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
807 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
808 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
809 priv->add_attachment_button = gtk_button_new ();
810 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
811 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
812 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
813 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
814 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
815 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
816 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
817 priv->attachments_view = modest_attachments_view_new (NULL);
819 priv->header_box = gtk_vbox_new (FALSE, 0);
821 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
822 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
823 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
824 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
825 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
826 g_object_unref (size_group);
828 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
829 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
830 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
831 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
832 gtk_size_group_add_widget (size_group, priv->subject_field);
833 gtk_size_group_add_widget (size_group, priv->attachments_view);
834 g_object_unref (size_group);
836 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
837 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
838 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
839 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
840 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
841 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
842 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
845 priv->msg_body = wp_text_view_new ();
846 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
847 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
848 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
849 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
850 #if (GTK_MINOR_VERSION >= 10)
851 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
852 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
854 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
855 deserialize_type, TRUE);
857 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
859 priv->find_toolbar = hildon_find_toolbar_new (NULL);
860 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
862 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
864 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
865 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
866 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
867 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
869 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
871 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
872 priv->frame = gtk_frame_new (NULL);
873 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
875 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
876 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
877 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
879 window_box = gtk_vbox_new (FALSE, 0);
880 gtk_container_add (GTK_CONTAINER(obj), window_box);
882 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
884 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
886 /* Set window icon */
887 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
889 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
890 g_object_unref (window_icon);
895 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
897 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
899 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
900 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
901 priv->clipboard_change_handler_id))
902 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
903 priv->clipboard_change_handler_id);
904 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
905 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
906 priv->default_clipboard_change_handler_id))
907 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
908 priv->default_clipboard_change_handler_id);
910 if (priv->account_removed_handler_id &&
911 g_signal_handler_is_connected (modest_runtime_get_account_store (),
912 priv->account_removed_handler_id))
913 g_signal_handler_disconnect(modest_runtime_get_account_store (),
914 priv->account_removed_handler_id);
918 modest_msg_edit_window_finalize (GObject *obj)
920 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
922 /* Sanity check: shouldn't be needed, the window mgr should
923 call this function before */
924 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
926 if (priv->font_dialog != NULL) {
927 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
930 if (priv->clipboard_text != NULL) {
931 g_free (priv->clipboard_text);
932 priv->clipboard_text = NULL;
935 if (priv->draft_msg != NULL) {
936 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
937 if (TNY_IS_HEADER (header)) {
938 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
939 modest_window_mgr_unregister_header (mgr, header);
941 g_object_unref (priv->draft_msg);
942 priv->draft_msg = NULL;
944 if (priv->outbox_msg != NULL) {
945 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
946 if (TNY_IS_HEADER (header)) {
947 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
948 modest_window_mgr_unregister_header (mgr, header);
950 g_object_unref (priv->outbox_msg);
951 priv->outbox_msg = NULL;
953 if (priv->scroll_drag_timeout_id > 0) {
954 g_source_remove (priv->scroll_drag_timeout_id);
955 priv->scroll_drag_timeout_id = 0;
957 if (priv->clipboard_owner_idle > 0) {
958 g_source_remove (priv->clipboard_owner_idle);
959 priv->clipboard_owner_idle = 0;
961 if (priv->original_account_name)
962 g_free (priv->original_account_name);
963 g_free (priv->msg_uid);
964 g_free (priv->last_search);
965 g_slist_free (priv->font_items_group);
966 g_slist_free (priv->size_items_group);
967 g_object_unref (priv->attachments);
968 g_object_unref (priv->images);
970 /* This had to stay alive for as long as the picker that used it: */
971 modest_pair_list_free (priv->from_field_protos);
973 G_OBJECT_CLASS(parent_class)->finalize (obj);
977 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
979 GdkPixbufLoader *loader;
985 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
987 if (loader == NULL) {
993 tny_stream_reset (TNY_STREAM (stream));
994 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
995 GError *error = NULL;
996 unsigned char read_buffer[128];
998 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1000 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1005 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1007 g_object_ref (pixbuf);
1008 gdk_pixbuf_loader_close (loader, NULL);
1009 g_object_unref (loader);
1014 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1015 GdkPixbuf *new_pixbuf;
1017 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1018 gdk_pixbuf_get_width (pixbuf);
1019 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1020 g_object_unref (pixbuf);
1021 pixbuf = new_pixbuf;
1025 *stream_size = size;
1031 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1033 ModestMsgEditWindowPrivate *priv;
1036 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1038 for (iter = tny_list_create_iterator (attachments);
1039 !tny_iterator_is_done (iter);
1040 tny_iterator_next (iter)) {
1041 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1042 const gchar *cid = tny_mime_part_get_content_id (part);
1043 const gchar *mime_type = tny_mime_part_get_content_type (part);
1044 if ((cid != NULL)&&(mime_type != NULL)) {
1045 guint64 stream_size;
1046 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1047 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1050 g_object_unref (stream);
1052 if (pixbuf != NULL) {
1053 priv->images_count ++;
1054 priv->images_size += stream_size;
1055 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1056 g_object_unref (pixbuf);
1059 g_object_unref (part);
1061 g_object_unref (iter);
1065 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1067 TnyMimePart *parent = NULL;
1068 const gchar *content_type = NULL;
1069 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1071 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1073 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1074 parent = g_object_ref (msg);
1075 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1076 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1079 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1080 iter = tny_list_create_iterator (parts);
1081 while (!tny_iterator_is_done (iter)) {
1083 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1084 content_type = tny_mime_part_get_content_type (part);
1085 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1089 g_object_unref (part);
1091 tny_iterator_next (iter);
1093 g_object_unref (iter);
1094 g_object_unref (parts);
1097 if (parent != NULL) {
1098 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1101 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1102 iter = tny_list_create_iterator (parts);
1103 while (!tny_iterator_is_done (iter)) {
1105 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1106 content_type = tny_mime_part_get_content_type (part);
1107 if (content_type && g_str_has_prefix (content_type, "image/")) {
1108 tny_list_prepend (priv->images, (GObject *) part);
1110 g_object_unref (part);
1111 tny_iterator_next (iter);
1113 g_object_unref (iter);
1114 g_object_unref (parts);
1115 g_object_unref (parent);
1120 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1123 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1125 for (iter = tny_list_create_iterator (attachments) ;
1126 !tny_iterator_is_done (iter);
1127 tny_iterator_next (iter)) {
1128 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1129 const gchar *cid = tny_mime_part_get_content_id (part);
1131 char *invalid = NULL;
1132 gint int_cid = strtol (cid, &invalid, 10);
1133 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1134 priv->next_cid = int_cid + 1;
1137 g_object_unref (part);
1139 g_object_unref (iter);
1143 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1146 gchar *to, *cc, *bcc, *subject;
1148 ModestMsgEditWindowPrivate *priv;
1150 TnyHeaderFlags priority_flags;
1151 TnyFolder *msg_folder;
1152 gboolean is_html = FALSE;
1154 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1155 g_return_if_fail (TNY_IS_MSG (msg));
1157 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1159 header = tny_msg_get_header (msg);
1160 to = tny_header_dup_to (header);
1161 cc = tny_header_dup_cc (header);
1162 bcc = tny_header_dup_bcc (header);
1163 subject = tny_header_dup_subject (header);
1164 priority_flags = tny_header_get_priority (header);
1167 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1169 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1170 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1171 gtk_widget_show (priv->cc_caption);
1172 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1173 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1174 gtk_widget_hide (priv->cc_caption);
1177 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1178 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1179 gtk_widget_show (priv->bcc_caption);
1180 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1181 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1182 gtk_widget_hide (priv->bcc_caption);
1185 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1186 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1189 update_window_title (self);
1191 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1192 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1194 if ((body == NULL)||(body[0] == '\0')) {
1196 body = modest_text_utils_convert_to_html ("");
1199 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1200 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1203 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1206 /* Add attachments to the view */
1207 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1208 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1209 if (tny_list_get_length (priv->attachments) == 0) {
1210 gtk_widget_hide (priv->attachments_caption);
1212 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1213 gtk_widget_show_all (priv->attachments_caption);
1215 get_related_images (self, msg);
1216 update_next_cid (self, priv->attachments);
1217 update_next_cid (self, priv->images);
1218 replace_with_images (self, priv->images);
1220 if (preserve_is_rich && !is_html) {
1221 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1222 /* Get the default format required from configuration */
1223 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1224 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1227 /* Set the default focus depending on having already a To: field or not */
1228 if ((!to)||(*to == '\0')) {
1229 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1231 gtk_widget_grab_focus (priv->msg_body);
1234 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1236 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1237 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1239 modest_msg_edit_window_set_modified (self, FALSE);
1241 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1242 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1243 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1244 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1246 if (priv->msg_uid) {
1247 g_free (priv->msg_uid);
1248 priv->msg_uid = NULL;
1251 /* we should set a reference to the incoming message if it is a draft */
1252 msg_folder = tny_msg_get_folder (msg);
1254 if (modest_tny_folder_is_local_folder (msg_folder)) {
1255 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1256 if (type == TNY_FOLDER_TYPE_INVALID)
1257 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1259 if (type == TNY_FOLDER_TYPE_DRAFTS)
1260 priv->draft_msg = g_object_ref(msg);
1261 if (type == TNY_FOLDER_TYPE_OUTBOX)
1262 priv->outbox_msg = g_object_ref(msg);
1263 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1265 g_object_unref (msg_folder);
1275 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1278 GList *item_children, *node;
1279 GtkWidget *bin_child;
1281 bin_child = gtk_bin_get_child (GTK_BIN(item));
1283 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1285 for (node = item_children; node != NULL; node = g_list_next (node)) {
1286 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1287 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1290 g_list_free (item_children);
1294 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1297 GList *item_children, *node;
1299 box = gtk_bin_get_child (GTK_BIN (item));
1300 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1301 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1303 for (node = item_children; node != NULL; node = g_list_next (node)) {
1304 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1305 if (GTK_IS_TOGGLE_BUTTON (node->data))
1306 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1307 else if (GTK_IS_BUTTON (node->data))
1308 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1310 g_list_free (item_children);
1315 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1317 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1318 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1319 GtkWidget *placeholder;
1320 GtkWidget *tool_item;
1325 GtkWidget *sizes_menu;
1326 GtkWidget *fonts_menu;
1327 GSList *radio_group = NULL;
1328 GSList *node = NULL;
1332 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1333 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1335 /* Font color placeholder */
1336 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1337 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1340 tool_item = GTK_WIDGET (gtk_tool_item_new ());
1341 priv->font_color_button = hildon_color_button_new ();
1342 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1343 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1344 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
1345 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1346 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1347 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1348 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1350 G_CALLBACK (modest_msg_edit_window_color_button_change),
1353 /* Font size and face placeholder */
1354 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1355 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1357 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1358 priv->size_tool_button_label = gtk_label_new (NULL);
1359 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1360 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1361 size_text,"</span>", NULL);
1362 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1364 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1365 sizes_menu = gtk_menu_new ();
1366 priv->size_items_group = NULL;
1368 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1369 GtkWidget *size_menu_item;
1371 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1372 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1373 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1374 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1375 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1376 gtk_widget_show (size_menu_item);
1378 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1382 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1383 GtkWidget *item = (GtkWidget *) node->data;
1384 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1388 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1389 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1390 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1391 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1392 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1393 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1394 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1395 priv->font_size_toolitem = tool_item;
1398 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1399 priv->font_tool_button_label = gtk_label_new (NULL);
1400 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1401 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1403 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1404 fonts_menu = gtk_menu_new ();
1405 priv->font_items_group = NULL;
1407 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1408 GtkWidget *font_menu_item;
1409 GtkWidget *child_label;
1411 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1412 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1413 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1414 wp_get_font_name (font_index), "</span>", NULL);
1415 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1418 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1419 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1420 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1421 gtk_widget_show (font_menu_item);
1423 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1426 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1427 GtkWidget *item = (GtkWidget *) node->data;
1428 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1431 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1432 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1433 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1434 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1435 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1436 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1437 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1438 priv->font_face_toolitem = tool_item;
1440 /* Set expand and homogeneous for remaining items */
1441 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1442 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1443 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1444 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
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/ActionsItalics");
1448 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1449 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1451 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1452 will not show the tool items added to the placeholders) */
1453 gtk_widget_show_all (parent_priv->toolbar);
1455 /* Set the no show all *after* showing all items. We do not
1456 want the toolbar to be shown with a show all because it
1457 could go agains the gconf setting regarding showing or not
1458 the toolbar of the editor window */
1459 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1465 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1468 ModestWindowPrivate *parent_priv;
1469 ModestMsgEditWindowPrivate *priv;
1470 ModestDimmingRulesGroup *menu_rules_group = NULL;
1471 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1472 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1473 ModestWindowMgr *mgr = NULL;
1475 g_return_val_if_fail (msg, NULL);
1476 g_return_val_if_fail (account_name, NULL);
1478 mgr = modest_runtime_get_window_mgr ();
1480 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1482 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1483 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1485 /* Menubar. Update the state of some toggles */
1486 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1487 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1488 priv->from_field_protos = get_transports ();
1489 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1490 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1491 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1493 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1494 hildon_touch_selector_get_current_text
1495 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1496 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1497 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1500 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1502 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1504 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1506 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1508 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1509 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1510 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1511 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1512 /* Add common dimming rules */
1513 modest_dimming_rules_group_add_rules (menu_rules_group,
1514 modest_msg_edit_window_menu_dimming_entries,
1515 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1516 MODEST_WINDOW (obj));
1517 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1518 modest_msg_edit_window_toolbar_dimming_entries,
1519 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1520 MODEST_WINDOW (obj));
1521 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1522 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1523 MODEST_WINDOW (obj));
1524 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1525 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1526 MODEST_WINDOW (obj));
1527 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1528 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1529 MODEST_WINDOW (obj));
1530 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1531 modest_msg_edit_window_clipboard_dimming_entries,
1532 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1533 MODEST_WINDOW (obj));
1534 /* Insert dimming rules group for this window */
1535 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1536 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1537 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1538 /* Checks the dimming rules */
1539 g_object_unref (menu_rules_group);
1540 g_object_unref (toolbar_rules_group);
1541 g_object_unref (clipboard_rules_group);
1542 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1544 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1546 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1547 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1548 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1549 priv->update_caption_visibility = TRUE;
1551 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1553 /* Track account-removed signal, this window should be closed
1554 in the case we're creating a mail associated to the account
1556 priv->account_removed_handler_id =
1557 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1559 G_CALLBACK(on_account_removed),
1562 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1564 return (ModestWindow*) obj;
1568 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1570 GString **string_buffer = (GString **) user_data;
1572 *string_buffer = g_string_append (*string_buffer, buffer);
1578 * @result: A new string which should be freed with g_free().
1581 get_formatted_data (ModestMsgEditWindow *edit_window)
1583 ModestMsgEditWindowPrivate *priv;
1584 GString *string_buffer = g_string_new ("");
1586 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1588 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1590 modest_text_utils_hyperlinkify (string_buffer);
1592 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1594 return g_string_free (string_buffer, FALSE);
1599 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1602 const gchar *account_name;
1603 ModestMsgEditWindowPrivate *priv;
1604 TnyIterator *att_iter;
1606 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1608 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1610 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1611 g_return_val_if_fail (account_name, NULL);
1614 /* don't free these (except from) */
1615 data = g_slice_new0 (MsgData);
1616 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1618 data->account_name = g_strdup (account_name);
1619 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1620 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1621 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1622 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1623 if (priv->draft_msg) {
1624 data->draft_msg = g_object_ref (priv->draft_msg);
1625 } else if (priv->outbox_msg) {
1626 data->draft_msg = g_object_ref (priv->outbox_msg);
1628 data->draft_msg = NULL;
1631 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1633 gtk_text_buffer_get_bounds (buf, &b, &e);
1634 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1636 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1637 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1639 data->html_body = NULL;
1641 /* deep-copy the data */
1642 att_iter = tny_list_create_iterator (priv->attachments);
1643 data->attachments = NULL;
1644 while (!tny_iterator_is_done (att_iter)) {
1645 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1646 if (!(TNY_IS_MIME_PART(part))) {
1647 g_warning ("strange data in attachment list");
1648 g_object_unref (part);
1649 tny_iterator_next (att_iter);
1652 data->attachments = g_list_append (data->attachments,
1654 tny_iterator_next (att_iter);
1656 g_object_unref (att_iter);
1658 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1659 att_iter = tny_list_create_iterator (priv->images);
1660 data->images = NULL;
1661 while (!tny_iterator_is_done (att_iter)) {
1662 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1664 if (!(TNY_IS_MIME_PART(part))) {
1665 g_warning ("strange data in attachment list");
1666 g_object_unref (part);
1667 tny_iterator_next (att_iter);
1670 cid = tny_mime_part_get_content_id (part);
1672 gchar *image_tag_id;
1673 GtkTextTag *image_tag;
1675 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1676 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1677 g_free (image_tag_id);
1679 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1681 ((gtk_text_iter_has_tag (&iter, image_tag))||
1682 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1683 data->images = g_list_append (data->images,
1684 g_object_ref (part));
1686 g_object_unref (part);
1687 tny_iterator_next (att_iter);
1689 g_object_unref (att_iter);
1691 data->priority_flags = priv->priority_flags;
1698 unref_gobject (GObject *obj, gpointer data)
1700 if (!G_IS_OBJECT(obj))
1702 g_object_unref (obj);
1706 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1709 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1717 g_free (data->from);
1718 g_free (data->subject);
1719 g_free (data->plain_body);
1720 g_free (data->html_body);
1721 g_free (data->account_name);
1723 if (data->draft_msg != NULL) {
1724 g_object_unref (data->draft_msg);
1725 data->draft_msg = NULL;
1728 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1729 g_list_free (data->attachments);
1730 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1731 g_list_free (data->images);
1733 g_slice_free (MsgData, data);
1737 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1739 guint64 *parts_size)
1741 ModestMsgEditWindowPrivate *priv;
1743 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1745 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1747 /* TODO: add images */
1748 *parts_size += priv->images_size;
1749 *parts_count += priv->images_count;
1754 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1757 ModestMsgEditWindowPrivate *priv = NULL;
1758 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1760 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1762 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1764 return MODEST_MSG_EDIT_FORMAT_HTML;
1766 return MODEST_MSG_EDIT_FORMAT_TEXT;
1770 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1771 ModestMsgEditFormat format)
1773 ModestMsgEditWindowPrivate *priv;
1775 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1776 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1779 case MODEST_MSG_EDIT_FORMAT_HTML:
1780 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1782 case MODEST_MSG_EDIT_FORMAT_TEXT:
1783 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1786 g_return_if_reached ();
1790 ModestMsgEditFormatState *
1791 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1793 ModestMsgEditFormatState *format_state = NULL;
1794 ModestMsgEditWindowPrivate *priv;
1795 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1797 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1798 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1800 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1802 format_state = g_new0 (ModestMsgEditFormatState, 1);
1803 format_state->bold = buffer_format->bold&0x1;
1804 format_state->italics = buffer_format->italic&0x1;
1805 format_state->bullet = buffer_format->bullet&0x1;
1806 format_state->color = buffer_format->color;
1807 format_state->font_size = buffer_format->font_size;
1808 format_state->font_family = wp_get_font_name (buffer_format->font);
1809 format_state->justification = buffer_format->justification;
1810 g_free (buffer_format);
1812 return format_state;
1817 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1818 const ModestMsgEditFormatState *format_state)
1820 ModestMsgEditWindowPrivate *priv;
1821 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1822 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1823 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1824 g_return_if_fail (format_state != NULL);
1826 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1827 gtk_widget_grab_focus (priv->msg_body);
1828 buffer_format->bold = (format_state->bold != FALSE);
1829 buffer_format->italic = (format_state->italics != FALSE);
1830 buffer_format->color = format_state->color;
1831 buffer_format->font_size = format_state->font_size;
1832 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1833 buffer_format->justification = format_state->justification;
1834 buffer_format->bullet = format_state->bullet;
1836 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1838 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1839 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1840 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1841 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1842 buffer_format->cs.font = (buffer_format->font != current_format->font);
1843 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1844 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1846 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1847 if (buffer_format->cs.bold) {
1848 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1849 GINT_TO_POINTER (buffer_format->bold&0x1));
1851 if (buffer_format->cs.italic) {
1852 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1853 GINT_TO_POINTER (buffer_format->italic&0x1));
1855 if (buffer_format->cs.color) {
1856 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1857 GINT_TO_POINTER (&(buffer_format->color)));
1859 if (buffer_format->cs.font_size) {
1860 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1861 GINT_TO_POINTER (buffer_format->font_size));
1863 if (buffer_format->cs.justification) {
1864 switch (buffer_format->justification) {
1865 case GTK_JUSTIFY_LEFT:
1866 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1867 GINT_TO_POINTER(TRUE));
1869 case GTK_JUSTIFY_CENTER:
1870 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1871 GINT_TO_POINTER(TRUE));
1873 case GTK_JUSTIFY_RIGHT:
1874 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1875 GINT_TO_POINTER(TRUE));
1882 if (buffer_format->cs.font) {
1883 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1884 GINT_TO_POINTER (buffer_format->font));
1886 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1887 if (buffer_format->cs.bullet) {
1888 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1889 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1891 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1893 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1895 g_free (current_format);
1897 /* Check dimming rules */
1898 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1899 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1903 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1905 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1907 ModestWindowPrivate *parent_priv;
1908 ModestMsgEditWindowPrivate *priv;
1909 GtkWidget *new_size_menuitem;
1910 GtkWidget *new_font_menuitem;
1912 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1913 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1915 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1916 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1917 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1918 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1920 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1921 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1922 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1925 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1927 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1928 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1930 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1931 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1933 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1934 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1937 switch (buffer_format->justification)
1939 case GTK_JUSTIFY_LEFT:
1940 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1942 case GTK_JUSTIFY_CENTER:
1943 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1945 case GTK_JUSTIFY_RIGHT:
1946 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1953 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1955 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1956 G_CALLBACK (modest_msg_edit_window_color_button_change),
1958 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1959 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1960 G_CALLBACK (modest_msg_edit_window_color_button_change),
1963 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1964 buffer_format->font_size))->data);
1965 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1969 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1970 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1971 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1973 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1974 G_CALLBACK (modest_msg_edit_window_size_change),
1976 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1977 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1978 G_CALLBACK (modest_msg_edit_window_size_change),
1982 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1983 buffer_format->font))->data);
1984 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1988 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1989 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1990 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1992 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1993 G_CALLBACK (modest_msg_edit_window_font_change),
1995 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1996 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1997 G_CALLBACK (modest_msg_edit_window_font_change),
2001 g_free (buffer_format);
2005 #ifdef MODEST_HILDON_VERSION_0
2007 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2010 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2011 ModestMsgEditWindowPrivate *priv;
2012 GtkWidget *dialog = NULL;
2014 GdkColor *new_color = NULL;
2016 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2017 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2019 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2020 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2021 g_free (buffer_format);
2023 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2024 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2025 if (new_color != NULL) {
2026 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2027 (gpointer) new_color);
2030 gtk_widget_destroy (dialog);
2035 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2038 ModestMsgEditWindowPrivate *priv;
2039 GtkWidget *dialog = NULL;
2041 GdkColor *old_color = NULL;
2042 const GdkColor *new_color = NULL;
2044 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2045 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2047 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2048 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2050 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2051 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2052 if (new_color != NULL)
2053 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2055 gtk_widget_destroy (dialog);
2061 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2064 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2065 ModestMsgEditWindowPrivate *priv;
2066 GtkWidget *dialog = NULL;
2068 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2069 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2071 dialog = hildon_color_chooser_new ();
2072 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2073 g_free (buffer_format);
2075 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2077 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2078 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2081 gtk_widget_destroy (dialog);
2086 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2089 ModestMsgEditWindowPrivate *priv;
2090 GtkWidget *dialog = NULL;
2091 GdkColor *old_color = NULL;
2093 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2094 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2096 dialog = hildon_color_chooser_new ();
2097 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2099 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2101 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2102 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2104 gtk_widget_destroy (dialog);
2107 #endif /*!MODEST_HILDON_VERSION_0*/
2112 create_stream_for_uri (const gchar* uri)
2117 TnyStream *result = NULL;
2119 GnomeVFSHandle *handle = NULL;
2120 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2121 if (test == GNOME_VFS_OK) {
2122 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2123 /* Streams over OBEX (Bluetooth) are not seekable but
2124 * we expect them to be (we might need to read them
2125 * several times). So if this is a Bluetooth URI just
2126 * read the whole file into memory (this is not a fast
2127 * protocol so we can assume that these files are not
2128 * going to be very big) */
2129 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2130 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2131 TnyStream *memstream = tny_camel_mem_stream_new ();
2132 tny_stream_write_to_stream (vfssstream, memstream);
2133 g_object_unref (vfssstream);
2136 result = vfssstream;
2144 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2147 ModestMsgEditWindowPrivate *priv;
2148 GtkWidget *dialog = NULL;
2150 GSList *uris = NULL;
2151 GSList *uri_node = NULL;
2153 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2155 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2156 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2157 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2159 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2161 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2162 GTK_WINDOW (dialog));
2164 response = gtk_dialog_run (GTK_DIALOG (dialog));
2166 case GTK_RESPONSE_OK:
2167 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2172 gtk_widget_destroy (dialog);
2174 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2176 GnomeVFSHandle *handle = NULL;
2177 GnomeVFSResult result;
2178 GtkTextIter position;
2179 GtkTextMark *insert_mark;
2181 uri = (const gchar *) uri_node->data;
2182 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2183 if (result == GNOME_VFS_OK) {
2185 GnomeVFSFileInfo *info;
2186 gchar *filename, *basename, *escaped_filename;
2187 TnyMimePart *mime_part;
2189 const gchar *mime_type = NULL;
2190 GnomeVFSURI *vfs_uri;
2191 guint64 stream_size;
2193 gnome_vfs_close (handle);
2194 vfs_uri = gnome_vfs_uri_new (uri);
2196 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2197 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2198 g_free (escaped_filename);
2199 gnome_vfs_uri_unref (vfs_uri);
2200 info = gnome_vfs_file_info_new ();
2202 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2203 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2205 mime_type = gnome_vfs_file_info_get_mime_type (info);
2207 mime_part = tny_platform_factory_new_mime_part
2208 (modest_runtime_get_platform_factory ());
2210 TnyStream *stream = create_stream_for_uri (uri);
2212 if (stream == NULL) {
2214 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2216 g_object_unref (mime_part);
2217 gnome_vfs_file_info_unref (info);
2221 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2223 content_id = g_strdup_printf ("%d", priv->next_cid);
2224 tny_mime_part_set_content_id (mime_part, content_id);
2225 g_free (content_id);
2228 basename = g_path_get_basename (filename);
2229 tny_mime_part_set_filename (mime_part, basename);
2232 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2234 if (pixbuf != NULL) {
2235 priv->images_size += stream_size;
2236 priv->images_count ++;
2237 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2238 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2239 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2242 tny_list_prepend (priv->images, (GObject *) mime_part);
2243 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2245 g_object_unref (mime_part);
2246 gnome_vfs_file_info_unref (info);
2255 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2257 GtkWidget *dialog = NULL;
2259 GSList *uris = NULL;
2261 GnomeVFSFileSize total_size, allowed_size;
2262 ModestMsgEditWindowPrivate *priv;
2266 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2268 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2270 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2273 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2274 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2275 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2276 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
2278 response = gtk_dialog_run (GTK_DIALOG (dialog));
2280 case GTK_RESPONSE_OK:
2281 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2286 gtk_widget_destroy (dialog);
2288 /* allowed size is the maximum size - what's already there */
2289 modest_attachments_view_get_sizes (
2290 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2291 &att_num, &att_size);
2292 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2295 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2297 const gchar *uri = (const gchar *) uri_node->data;
2299 total_size += modest_msg_edit_window_attach_file_one
2300 (window, uri, allowed_size);
2302 if (total_size > allowed_size) {
2303 g_warning ("%s: total size: %u",
2304 __FUNCTION__, (unsigned int)total_size);
2308 allowed_size -= total_size;
2312 g_slist_foreach (uris, (GFunc) g_free, NULL);
2313 g_slist_free (uris);
2318 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2320 GnomeVFSFileSize allowed_size)
2323 GnomeVFSHandle *handle = NULL;
2324 ModestMsgEditWindowPrivate *priv;
2325 GnomeVFSResult result;
2326 GnomeVFSFileSize size = 0;
2327 g_return_val_if_fail (window, 0);
2328 g_return_val_if_fail (uri, 0);
2330 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2332 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2333 if (result == GNOME_VFS_OK) {
2334 TnyMimePart *mime_part;
2336 const gchar *mime_type = NULL;
2338 gchar *escaped_filename;
2341 GnomeVFSFileInfo *info;
2342 GnomeVFSURI *vfs_uri;
2344 gnome_vfs_close (handle);
2345 vfs_uri = gnome_vfs_uri_new (uri);
2348 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2349 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2350 g_free (escaped_filename);
2351 gnome_vfs_uri_unref (vfs_uri);
2353 info = gnome_vfs_file_info_new ();
2355 if (gnome_vfs_get_file_info (uri,
2357 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2359 mime_type = gnome_vfs_file_info_get_mime_type (info);
2360 mime_part = tny_platform_factory_new_mime_part
2361 (modest_runtime_get_platform_factory ());
2363 /* try to get the attachment's size; this may fail for weird
2364 * file systems, like obex, upnp... */
2365 if (allowed_size != 0 &&
2366 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2368 if (size > allowed_size) {
2369 modest_platform_information_banner (NULL, NULL,
2370 dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2374 g_warning ("%s: could not get attachment size", __FUNCTION__);
2376 stream = create_stream_for_uri (uri);
2378 if (stream == NULL) {
2380 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2382 g_object_unref (mime_part);
2383 gnome_vfs_file_info_unref (info);
2387 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2388 g_object_unref (stream);
2390 content_id = g_strdup_printf ("%d", priv->next_cid);
2391 tny_mime_part_set_content_id (mime_part, content_id);
2392 g_free (content_id);
2395 basename = g_path_get_basename (filename);
2396 tny_mime_part_set_filename (mime_part, basename);
2399 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2400 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2402 info->size == 0, info->size);
2403 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2404 gtk_widget_show_all (priv->attachments_caption);
2405 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2407 g_object_unref (mime_part);
2408 gnome_vfs_file_info_unref (info);
2415 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2418 ModestMsgEditWindowPrivate *priv;
2421 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2422 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2424 if (att_list == NULL) {
2425 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2427 g_object_ref (att_list);
2430 if (tny_list_get_length (att_list) == 0) {
2431 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2433 gboolean dialog_response;
2434 gchar *message = NULL;
2435 gchar *filename = NULL;
2437 if (tny_list_get_length (att_list) == 1) {
2439 iter = tny_list_create_iterator (att_list);
2440 part = (TnyMimePart *) tny_iterator_get_current (iter);
2441 g_object_unref (iter);
2442 if (TNY_IS_MSG (part)) {
2443 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2445 filename = tny_header_dup_subject (header);
2446 g_object_unref (header);
2448 if (filename == NULL) {
2449 filename = g_strdup (_("mail_va_no_subject"));
2452 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2454 g_object_unref (part);
2456 filename = g_strdup ("");
2458 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2459 tny_list_get_length (att_list)), filename);
2462 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2465 if (dialog_response != GTK_RESPONSE_OK) {
2466 g_object_unref (att_list);
2469 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
2471 for (iter = tny_list_create_iterator (att_list);
2472 !tny_iterator_is_done (iter);
2473 tny_iterator_next (iter)) {
2474 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2475 const gchar *att_id;
2476 tny_list_remove (priv->attachments, (GObject *) mime_part);
2478 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2480 if (tny_list_get_length (priv->attachments) == 0)
2481 gtk_widget_hide (priv->attachments_caption);
2482 att_id = tny_mime_part_get_content_id (mime_part);
2484 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2486 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2487 g_object_unref (mime_part);
2489 g_object_unref (iter);
2492 g_object_unref (att_list);
2494 /* if the last attachment has been removed, focus the Subject: field */
2495 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2496 gtk_widget_grab_focus (priv->subject_field);
2500 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2503 ModestMsgEditWindowPrivate *priv;
2504 GdkColor *new_color;
2505 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2507 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2508 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2511 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2513 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2515 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2517 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2522 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2525 ModestMsgEditWindowPrivate *priv;
2526 gint new_size_index;
2527 ModestMsgEditWindow *window;
2530 window = MODEST_MSG_EDIT_WINDOW (userdata);
2531 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2532 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2534 if (gtk_check_menu_item_get_active (menu_item)) {
2536 WPTextBufferFormat format;
2538 memset (&format, 0, sizeof (format));
2539 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2541 label = gtk_bin_get_child (GTK_BIN (menu_item));
2543 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2544 format.cs.font_size = TRUE;
2545 format.cs.text_position = TRUE;
2546 format.cs.font = TRUE;
2547 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2548 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2550 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2551 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2552 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2554 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2555 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2556 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2562 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2565 ModestMsgEditWindowPrivate *priv;
2566 gint new_font_index;
2567 ModestMsgEditWindow *window;
2570 window = MODEST_MSG_EDIT_WINDOW (userdata);
2571 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2572 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2574 if (gtk_check_menu_item_get_active (menu_item)) {
2577 label = gtk_bin_get_child (GTK_BIN (menu_item));
2579 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2581 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2582 GINT_TO_POINTER(new_font_index)))
2583 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2585 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2586 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2587 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2593 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2595 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2596 ModestWindowPrivate *parent_priv;
2597 ModestWindowMgr *mgr;
2598 gboolean is_fullscreen;
2599 GtkAction *fs_toggle_action;
2602 mgr = modest_runtime_get_window_mgr ();
2603 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2605 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2607 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2608 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2609 if (is_fullscreen != active)
2610 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2618 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2621 ModestMsgEditWindowPrivate *priv = NULL;
2622 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2624 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2625 if (!priv->update_caption_visibility)
2628 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2630 gtk_widget_show (priv->cc_caption);
2632 gtk_widget_hide (priv->cc_caption);
2634 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2638 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2641 ModestMsgEditWindowPrivate *priv = NULL;
2642 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2644 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2645 if (!priv->update_caption_visibility)
2648 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2650 gtk_widget_show (priv->bcc_caption);
2652 gtk_widget_hide (priv->bcc_caption);
2654 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2658 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2659 ModestRecptEditor *editor)
2661 ModestMsgEditWindowPrivate *priv;
2663 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2664 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2666 /* we check for low-mem; in that case, show a warning, and don't allow
2667 * for the addressbook
2669 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2672 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2674 if (editor == NULL) {
2675 GtkWidget *view_focus;
2676 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2678 /* This code should be kept in sync with ModestRecptEditor. The
2679 textview inside the recpt editor is the one that really gets the
2680 focus. As it's inside a scrolled window, and this one inside the
2681 hbox recpt editor inherits from, we'll need to go up in the
2682 hierarchy to know if the text view is part of the recpt editor
2683 or if it's a different text entry */
2685 if (gtk_widget_get_parent (view_focus)) {
2686 GtkWidget *first_parent;
2688 first_parent = gtk_widget_get_parent (view_focus);
2689 if (gtk_widget_get_parent (first_parent) &&
2690 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2691 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2696 editor = MODEST_RECPT_EDITOR (priv->to_field);
2700 modest_address_book_select_addresses (editor);
2705 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2707 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2709 modest_msg_edit_window_open_addressbook (window, NULL);
2713 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2714 gboolean show_toolbar)
2716 ModestWindowPrivate *parent_priv;
2717 const gchar *action_name;
2720 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2721 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2723 /* We can not just use the code of
2724 modest_msg_edit_window_setup_toolbar because it has a
2725 mixture of both initialization and creation code. */
2727 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2729 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2731 /* Update also the actions (to update the toggles in the
2732 menus), we have to do it manually because some other window
2733 of the same time could have changed it (remember that the
2734 toolbar fullscreen mode is shared by all the windows of the
2736 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2737 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2739 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2741 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2742 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2748 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2749 TnyHeaderFlags priority_flags)
2751 ModestMsgEditWindowPrivate *priv;
2752 ModestWindowPrivate *parent_priv;
2754 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2756 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2757 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2759 if (priv->priority_flags != priority_flags) {
2760 GtkAction *priority_action = NULL;
2762 priv->priority_flags = priority_flags;
2764 switch (priority_flags) {
2765 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2766 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2767 gtk_widget_show (priv->priority_icon);
2768 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2769 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2771 case TNY_HEADER_FLAG_LOW_PRIORITY:
2772 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2773 gtk_widget_show (priv->priority_icon);
2774 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2775 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2778 gtk_widget_hide (priv->priority_icon);
2779 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2780 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2783 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2784 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2789 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2792 ModestMsgEditWindowPrivate *priv;
2793 ModestWindowPrivate *parent_priv;
2794 gint current_format;
2796 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2798 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2799 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2801 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2802 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2804 if (current_format != file_format) {
2805 switch (file_format) {
2806 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2807 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2808 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2810 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2814 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2815 response = gtk_dialog_run (GTK_DIALOG (dialog));
2816 gtk_widget_destroy (dialog);
2817 if (response == GTK_RESPONSE_OK) {
2818 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2820 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2821 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2826 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2827 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2828 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2833 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2836 ModestMsgEditWindowPrivate *priv;
2837 WPTextBufferFormat oldfmt, fmt;
2838 gint old_position = 0;
2842 GdkColor *color = NULL;
2843 gboolean bold, bold_set, italic, italic_set;
2844 gboolean underline, underline_set;
2845 gboolean strikethrough, strikethrough_set;
2846 gboolean position_set;
2847 gboolean font_size_set, font_set, color_set;
2850 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2851 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2853 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2854 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2855 GTK_WINDOW(dialog));
2857 /* First we get the currently selected font information */
2858 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2860 switch (oldfmt.text_position) {
2861 case TEXT_POSITION_NORMAL:
2864 case TEXT_POSITION_SUPERSCRIPT:
2872 g_object_set (G_OBJECT (dialog),
2873 "bold", oldfmt.bold != FALSE,
2874 "bold-set", !oldfmt.cs.bold,
2875 "underline", oldfmt.underline != FALSE,
2876 "underline-set", !oldfmt.cs.underline,
2877 "italic", oldfmt.italic != FALSE,
2878 "italic-set", !oldfmt.cs.italic,
2879 "strikethrough", oldfmt.strikethrough != FALSE,
2880 "strikethrough-set", !oldfmt.cs.strikethrough,
2881 "color", &oldfmt.color,
2882 "color-set", !oldfmt.cs.color,
2883 "size", wp_font_size[oldfmt.font_size],
2884 "size-set", !oldfmt.cs.font_size,
2885 "position", old_position,
2886 "position-set", !oldfmt.cs.text_position,
2887 "family", wp_get_font_name (oldfmt.font),
2888 "family-set", !oldfmt.cs.font,
2891 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2892 GTK_WINDOW (dialog));
2893 gtk_widget_show_all (dialog);
2894 priv->font_dialog = dialog;
2895 response = gtk_dialog_run (GTK_DIALOG (dialog));
2896 priv->font_dialog = NULL;
2897 if (response == GTK_RESPONSE_OK) {
2899 g_object_get( dialog,
2901 "bold-set", &bold_set,
2902 "underline", &underline,
2903 "underline-set", &underline_set,
2905 "italic-set", &italic_set,
2906 "strikethrough", &strikethrough,
2907 "strikethrough-set", &strikethrough_set,
2909 "color-set", &color_set,
2911 "size-set", &font_size_set,
2912 "family", &font_name,
2913 "family-set", &font_set,
2914 "position", &position,
2915 "position-set", &position_set,
2920 if (response == GTK_RESPONSE_OK) {
2921 memset(&fmt, 0, sizeof(fmt));
2927 fmt.italic = italic;
2928 fmt.cs.italic = TRUE;
2930 if (underline_set) {
2931 fmt.underline = underline;
2932 fmt.cs.underline = TRUE;
2934 if (strikethrough_set) {
2935 fmt.strikethrough = strikethrough;
2936 fmt.cs.strikethrough = TRUE;
2941 ? TEXT_POSITION_NORMAL
2942 : ( ( position == 1 )
2943 ? TEXT_POSITION_SUPERSCRIPT
2944 : TEXT_POSITION_SUBSCRIPT );
2945 fmt.cs.text_position = TRUE;
2946 fmt.font_size = oldfmt.font_size;
2950 fmt.cs.color = TRUE;
2953 fmt.font = wp_get_font_index(font_name,
2958 if (font_size_set) {
2959 fmt.cs.font_size = TRUE;
2960 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2962 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2963 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2965 gtk_widget_destroy (dialog);
2967 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2971 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2973 ModestMsgEditWindowPrivate *priv;
2975 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2976 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2978 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2980 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2981 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2985 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2987 ModestMsgEditWindowPrivate *priv;
2989 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2990 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2992 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2994 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2995 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3000 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3002 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3004 priv->can_undo = can_undo;
3008 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3010 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3012 priv->can_redo = can_redo;
3016 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3018 ModestMsgEditWindowPrivate *priv;
3019 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3020 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3022 return priv->can_undo;
3026 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3028 ModestMsgEditWindowPrivate *priv;
3029 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3030 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3032 return priv->can_redo;
3037 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3040 GtkTextIter match_start, match_end;
3042 if (image_id == NULL)
3045 gtk_text_buffer_get_start_iter (buffer, &iter);
3047 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3048 GSList *tags = gtk_text_iter_get_tags (&match_start);
3050 for (node = tags; node != NULL; node = g_slist_next (node)) {
3051 GtkTextTag *tag = (GtkTextTag *) node->data;
3052 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3053 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3054 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3056 offset = gtk_text_iter_get_offset (&match_start);
3057 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3058 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3062 gtk_text_iter_forward_char (&iter);
3067 message_is_empty (ModestMsgEditWindow *window)
3069 ModestMsgEditWindowPrivate *priv = NULL;
3071 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3072 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3074 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3075 * so we can ignore markup.
3077 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3080 count = gtk_text_buffer_get_char_count (buf);
3086 msg_body_focus (GtkWidget *focus,
3087 GdkEventFocus *event,
3091 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3092 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3093 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3098 recpt_field_changed (GtkTextBuffer *buffer,
3099 ModestMsgEditWindow *editor)
3101 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3102 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3106 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3108 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3109 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3113 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3116 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3117 GtkTextBuffer *buffer;
3119 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3120 gtk_text_buffer_set_modified (buffer, modified);
3121 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3122 gtk_text_buffer_set_modified (buffer, modified);
3123 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3124 gtk_text_buffer_set_modified (buffer, modified);
3125 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3129 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3131 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3132 const char *account_name;
3133 GtkTextBuffer *buffer;
3135 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3136 if (gtk_text_buffer_get_modified (buffer))
3138 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3139 if (gtk_text_buffer_get_modified (buffer))
3141 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3142 if (gtk_text_buffer_get_modified (buffer))
3144 if (gtk_text_buffer_get_modified (priv->text_buffer))
3146 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3147 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3158 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3160 ModestMsgEditWindowPrivate *priv = NULL;
3162 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3163 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3165 /* check if there's no recipient added */
3166 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3167 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3168 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3169 /* no recipient contents, then select contacts */
3170 modest_msg_edit_window_open_addressbook (window, NULL);
3174 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3175 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3178 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3179 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3182 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3183 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3187 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3188 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3189 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3196 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3197 ModestMsgEditWindow *window)
3199 modest_msg_edit_window_offer_attach_file (window);
3203 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3205 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3207 return priv->clipboard_text;
3211 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3213 ModestMsgEditWindow *window)
3215 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3216 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3218 if (!GTK_WIDGET_VISIBLE (window))
3221 g_object_ref (window);
3222 text = gtk_clipboard_wait_for_text (selection_clipboard);
3224 if (priv->clipboard_text != NULL) {
3225 g_free (priv->clipboard_text);
3227 priv->clipboard_text = text;
3229 if (GTK_WIDGET_VISIBLE (window)) {
3230 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3232 g_object_unref (window);
3235 static gboolean clipboard_owner_change_idle (gpointer userdata)
3237 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3238 ModestMsgEditWindowPrivate *priv;
3240 gdk_threads_enter ();
3241 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3242 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3244 priv->clipboard_owner_idle = 0;
3245 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3246 gdk_threads_leave ();
3252 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3254 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3255 if (priv->clipboard_owner_idle == 0) {
3256 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3261 subject_field_move_cursor (GtkEntry *entry,
3262 GtkMovementStep step,
3267 if (!GTK_WIDGET_VISIBLE (window))
3270 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3274 update_window_title (ModestMsgEditWindow *window)
3276 ModestMsgEditWindowPrivate *priv = NULL;
3277 const gchar *subject;
3279 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3280 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3281 if (subject == NULL || subject[0] == '\0')
3282 subject = _("mail_va_new_email");
3284 gtk_window_set_title (GTK_WINDOW (window), subject);
3289 subject_field_changed (GtkEditable *editable,
3290 ModestMsgEditWindow *window)
3292 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3293 update_window_title (window);
3294 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3295 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3296 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3300 subject_field_insert_text (GtkEditable *editable,
3302 gint new_text_length,
3304 ModestMsgEditWindow *window)
3306 GString *result = g_string_new ("");
3308 gint result_len = 0;
3309 const gchar *entry_text = NULL;
3312 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3313 old_length = g_utf8_strlen (entry_text, -1);
3315 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3316 gunichar c = g_utf8_get_char_validated (current, 8);
3317 /* Invalid unichar, stop */
3323 result = g_string_append_unichar (result, c);
3327 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3328 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3331 /* Prevent endless recursion */
3332 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3333 g_signal_emit_by_name (editable, "insert-text",
3334 (gpointer) result->str, (gpointer) result->len,
3335 (gpointer) position, (gpointer) window);
3336 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3340 if (result_len + old_length > 1000) {
3341 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3342 dgettext("hildon-common-strings",
3343 "ckdg_ib_maximum_characters_reached"));
3346 g_string_free (result, TRUE);
3350 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3353 ModestMsgEditWindowPrivate *priv = NULL;
3355 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3356 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3358 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3361 gtk_widget_show_all (priv->find_toolbar);
3362 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3364 gtk_widget_hide_all (priv->find_toolbar);
3365 gtk_widget_grab_focus (priv->msg_body);
3371 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3373 GtkTextIter *match_start,
3374 GtkTextIter *match_end)
3376 GtkTextIter end_iter;
3377 gchar *str_casefold;
3380 gchar *range_casefold;
3383 gboolean result = FALSE;
3390 gtk_text_iter_forward_to_end (&end_iter);
3392 str_casefold = g_utf8_casefold (str, -1);
3393 str_chars_n = strlen (str);
3395 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3396 range_casefold = g_utf8_casefold (range_text, -1);
3397 range_chars_n = strlen (range_casefold);
3399 if (range_chars_n < str_chars_n) {
3400 g_free (str_casefold);
3401 g_free (range_text);
3402 g_free (range_casefold);
3406 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3407 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3408 if (!g_utf8_collate (range_subtext, str_casefold)) {
3409 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3411 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3412 match_start, match_end, NULL);
3413 g_free (found_text);
3415 g_free (range_subtext);
3419 g_free (str_casefold);
3420 g_free (range_text);
3421 g_free (range_casefold);
3428 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3429 ModestMsgEditWindow *window)
3431 gchar *current_search = NULL;
3432 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3434 GtkTextIter selection_start, selection_end;
3435 GtkTextIter match_start, match_end;
3436 gboolean continue_search = FALSE;
3438 if (message_is_empty (window)) {
3439 g_free (priv->last_search);
3440 priv->last_search = NULL;
3441 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3445 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3446 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3447 g_free (current_search);
3448 g_free (priv->last_search);
3449 priv->last_search = NULL;
3450 /* Information banner about empty search */
3451 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3455 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3456 continue_search = TRUE;
3458 g_free (priv->last_search);
3459 priv->last_search = g_strdup (current_search);
3462 if (continue_search) {
3463 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3464 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3465 &match_start, &match_end);
3467 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3469 GtkTextIter buffer_start;
3470 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3471 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3472 &match_start, &match_end);
3474 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3477 /* Mark as selected the string found in search */
3479 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3480 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3481 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3483 g_free (priv->last_search);
3484 priv->last_search = NULL;
3486 g_free (current_search);
3490 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3491 ModestMsgEditWindow *window)
3493 GtkToggleAction *toggle;
3494 ModestWindowPrivate *parent_priv;
3495 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3497 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3498 gtk_toggle_action_set_active (toggle, FALSE);
3502 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3504 ModestMsgEditWindowPrivate *priv;
3506 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3511 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3514 ModestMsgEditWindowPrivate *priv;
3516 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3522 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3525 ModestMsgEditWindowPrivate *priv;
3526 TnyHeader *header = NULL;
3528 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3529 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3531 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3532 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3534 if (priv->draft_msg != NULL) {
3535 g_object_unref (priv->draft_msg);
3538 if (draft != NULL) {
3539 g_object_ref (draft);
3540 header = tny_msg_get_header (draft);
3541 if (priv->msg_uid) {
3542 g_free (priv->msg_uid);
3543 priv->msg_uid = NULL;
3545 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3546 if (GTK_WIDGET_REALIZED (window))
3547 modest_window_mgr_register_window (mgr, MODEST_WINDOW (window));
3550 priv->draft_msg = draft;
3554 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3555 GtkTextIter *start, GtkTextIter *end,
3558 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3559 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3562 if (tag == NULL+13) return;
3563 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3564 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3565 replace_with_images (window, priv->images);
3570 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3573 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3575 g_return_if_fail (TNY_IS_MIME_PART (part));
3576 tny_list_prepend (priv->attachments, (GObject *) part);
3577 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3578 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3579 gtk_widget_show_all (priv->attachments_caption);
3580 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3584 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3586 ModestMsgEditWindowPrivate *priv;
3588 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3589 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3591 return priv->msg_uid;
3595 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3596 ModestMsgEditWindowWidgetType widget_type)
3598 ModestMsgEditWindowPrivate *priv;
3600 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3601 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3603 switch (widget_type) {
3604 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3605 return priv->msg_body;
3607 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3608 return priv->to_field;
3610 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3611 return priv->cc_field;
3613 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3614 return priv->bcc_field;
3616 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3617 return priv->subject_field;
3619 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3620 return priv->attachments_view;
3628 remove_tags (WPTextBuffer *buffer)
3630 GtkTextIter start, end;
3632 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3633 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3635 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3639 on_account_removed (TnyAccountStore *account_store,
3640 TnyAccount *account,
3643 /* Do nothing if it's a store account, because we use the
3644 transport to send the messages */
3645 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3646 const gchar *parent_acc = NULL;
3647 const gchar *our_acc = NULL;
3649 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3650 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3651 /* Close this window if I'm showing a message of the removed account */
3652 if (strcmp (parent_acc, our_acc) == 0)
3653 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3658 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3660 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3662 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3668 set_zoom_do_nothing (ModestWindow *window,
3674 get_zoom_do_nothing (ModestWindow *window)