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"
81 #include <modest-ui-constants.h>
84 #define DEFAULT_FONT_SIZE 3
85 #define DEFAULT_FONT 2
86 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
87 #define DEFAULT_MAIN_VBOX_SPACING 6
88 #define SUBJECT_MAX_LENGTH 1000
89 #define IMAGE_MAX_WIDTH 560
90 #define DEFAULT_FONT_SCALE 1.5
92 static gboolean is_wp_text_buffer_started = FALSE;
94 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
95 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
96 static void modest_msg_edit_window_finalize (GObject *obj);
98 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
99 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
100 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
102 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
103 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
104 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
105 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
106 GtkTextIter *start, GtkTextIter *end,
108 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
109 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
110 static void subject_field_insert_text (GtkEditable *editable,
112 gint new_text_length,
114 ModestMsgEditWindow *window);
115 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
117 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
119 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
121 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
122 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
123 GdkEventWindowState *event,
125 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
126 ModestRecptEditor *editor);
127 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
128 ModestMsgEditWindow *window);
130 /* ModestWindow methods implementation */
131 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
132 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
133 gboolean show_toolbar);
134 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
136 ModestMsgEditWindow *window);
137 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
138 static void subject_field_move_cursor (GtkEntry *entry,
139 GtkMovementStep step,
143 static void update_window_title (ModestMsgEditWindow *window);
146 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
147 ModestMsgEditWindow *window);
148 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
149 ModestMsgEditWindow *window);
150 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
152 GtkTextIter *match_start,
153 GtkTextIter *match_end);
155 static void remove_tags (WPTextBuffer *buffer);
157 static void on_account_removed (TnyAccountStore *account_store,
161 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
162 static void set_zoom_do_nothing (ModestWindow *window, gdouble zoom);
163 static gdouble get_zoom_do_nothing (ModestWindow *window);
165 static void init_window (ModestMsgEditWindow *obj);
167 gboolean scroll_drag_timeout (gpointer userdata);
168 static void correct_scroll (ModestMsgEditWindow *w);
169 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
170 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
171 ModestMsgEditWindow *userdata);
172 static void text_buffer_mark_set (GtkTextBuffer *buffer,
175 ModestMsgEditWindow *userdata);
176 static void vadj_changed (GtkAdjustment *adj,
177 ModestMsgEditWindow *window);
179 static void DEBUG_BUFFER (WPTextBuffer *buffer)
183 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
185 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
186 while (!gtk_text_iter_is_end (&iter)) {
187 GString *output = g_string_new ("");
188 GSList *toggled_tags;
191 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
192 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
193 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
194 GtkTextTag *tag = (GtkTextTag *) node->data;
196 g_object_get (G_OBJECT (tag), "name", &name, NULL);
197 output = g_string_append (output, name);
198 g_string_append (output, " ");
200 output = g_string_append (output, "] OPENED [ ");
201 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
202 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
203 GtkTextTag *tag = (GtkTextTag *) node->data;
205 g_object_get (G_OBJECT (tag), "name", &name, NULL);
206 output = g_string_append (output, name);
207 g_string_append (output, " ");
209 output = g_string_append (output, "]\n");
210 g_message ("%s", output->str);
211 g_string_free (output, TRUE);
212 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
214 g_message ("END BUFFER");
219 /* static gboolean */
220 /* on_key_pressed (GtkWidget *self, */
221 /* GdkEventKey *event, */
222 /* gpointer user_data); */
224 /* list my signals */
231 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
232 struct _ModestMsgEditWindowPrivate {
235 GtkWidget *header_box;
237 ModestPairList *from_field_protos;
238 GtkWidget *from_field;
239 gchar *original_account_name;
243 GtkWidget *bcc_field;
244 GtkWidget *subject_field;
245 GtkWidget *attachments_view;
246 GtkWidget *priority_icon;
247 GtkWidget *add_attachment_button;
249 GtkWidget *cc_caption;
250 GtkWidget *bcc_caption;
251 gboolean update_caption_visibility;
252 GtkWidget *attachments_caption;
254 GtkTextBuffer *text_buffer;
256 GtkWidget *font_size_toolitem;
257 GtkWidget *font_face_toolitem;
258 GtkWidget *font_color_button;
259 GSList *font_items_group;
260 GtkWidget *font_tool_button_label;
261 GSList *size_items_group;
262 GtkWidget *size_tool_button_label;
264 GtkWidget *find_toolbar;
267 GtkWidget *font_dialog;
270 guint scroll_drag_timeout_id;
274 TnyList *attachments;
279 TnyHeaderFlags priority_flags;
281 gboolean can_undo, can_redo;
282 gulong clipboard_change_handler_id;
283 gulong default_clipboard_change_handler_id;
284 gulong account_removed_handler_id;
285 guint clipboard_owner_idle;
286 gchar *clipboard_text;
295 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
296 MODEST_TYPE_MSG_EDIT_WINDOW, \
297 ModestMsgEditWindowPrivate))
299 static GtkWindowClass *parent_class = NULL;
301 /* uncomment the following if you have defined any signals */
302 /* static guint signals[LAST_SIGNAL] = {0}; */
305 modest_msg_edit_window_get_type (void)
307 static GType my_type = 0;
309 static const GTypeInfo my_info = {
310 sizeof(ModestMsgEditWindowClass),
311 NULL, /* base init */
312 NULL, /* base finalize */
313 (GClassInitFunc) modest_msg_edit_window_class_init,
314 NULL, /* class finalize */
315 NULL, /* class data */
316 sizeof(ModestMsgEditWindow),
318 (GInstanceInitFunc) modest_msg_edit_window_init,
321 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
322 "ModestMsgEditWindow",
330 save_state (ModestWindow *self)
332 modest_widget_memory_save (modest_runtime_get_conf(),
333 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
338 restore_settings (ModestMsgEditWindow *self)
340 ModestConf *conf = NULL;
342 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
344 conf = modest_runtime_get_conf ();
345 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
346 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
347 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
348 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL));
349 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
350 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu");
351 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
352 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
354 /* set initial state of cc and bcc */
355 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
356 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
357 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
358 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
359 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
360 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
362 /* Dim at start clipboard actions */
363 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
364 gtk_action_set_sensitive (action, FALSE);
365 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
366 gtk_action_set_sensitive (action, FALSE);
367 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
368 gtk_action_set_sensitive (action, FALSE);
370 modest_widget_memory_restore (conf,
371 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
376 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
378 GObjectClass *gobject_class;
379 ModestWindowClass *modest_window_class;
380 gobject_class = (GObjectClass*) klass;
381 modest_window_class = (ModestWindowClass*) klass;
383 parent_class = g_type_class_peek_parent (klass);
384 gobject_class->finalize = modest_msg_edit_window_finalize;
386 modest_window_class->set_zoom_func = set_zoom_do_nothing;
387 modest_window_class->get_zoom_func = get_zoom_do_nothing;
388 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
389 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
390 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
391 modest_window_class->save_state_func = save_state;
392 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
394 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
398 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
400 ModestMsgEditWindowPrivate *priv;
401 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
403 priv->msg_body = NULL;
405 priv->from_field = NULL;
406 priv->to_field = NULL;
407 priv->cc_field = NULL;
408 priv->bcc_field = NULL;
409 priv->subject_field = NULL;
410 priv->attachments = TNY_LIST (tny_simple_list_new ());
411 priv->images = TNY_LIST (tny_simple_list_new ());
412 priv->images_size = 0;
413 priv->images_count = 0;
416 priv->cc_caption = NULL;
417 priv->bcc_caption = NULL;
418 priv->update_caption_visibility = FALSE;
420 priv->priority_flags = 0;
422 priv->find_toolbar = NULL;
423 priv->last_search = NULL;
425 priv->draft_msg = NULL;
426 priv->outbox_msg = NULL;
427 priv->msg_uid = NULL;
429 priv->can_undo = FALSE;
430 priv->can_redo = FALSE;
431 priv->clipboard_change_handler_id = 0;
432 priv->default_clipboard_change_handler_id = 0;
433 priv->account_removed_handler_id = 0;
434 priv->clipboard_owner_idle = 0;
435 priv->clipboard_text = NULL;
438 priv->scroll_drag_timeout_id = 0;
439 priv->last_upper = 0.0;
441 priv->font_dialog = NULL;
443 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
444 GTK_WINDOW(obj),"applications_email_editor");
446 if (!is_wp_text_buffer_started) {
447 is_wp_text_buffer_started = TRUE;
448 wp_text_buffer_library_init ();
453 hildon_program_add_window (hildon_program_get_instance(),
458 /* FIXME: this is a dup from the one in gtk/ */
461 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
463 static ModestPairList*
464 get_transports (void)
466 GSList *transports = NULL;
468 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
469 GSList *accounts = modest_account_mgr_account_names (account_mgr,
470 TRUE /* only enabled accounts. */);
472 GSList *cursor = accounts;
474 gchar *account_name = cursor->data;
475 gchar *from_string = NULL;
477 from_string = modest_account_mgr_get_from_string (account_mgr,
481 if (from_string && account_name) {
482 gchar *name = account_name;
483 ModestPair *pair = modest_pair_new ((gpointer) name,
484 (gpointer) from_string , TRUE);
485 transports = g_slist_prepend (transports, pair);
488 cursor = cursor->next;
490 g_slist_free (accounts); /* only free the accounts, not the elements,
491 * because they are used in the pairlist */
495 static void window_focus (GtkWindow *window,
499 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
503 scroll_drag_timeout (gpointer userdata)
505 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
506 ModestMsgEditWindowPrivate *priv;
508 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
510 correct_scroll_without_drag_check (win, TRUE);
512 priv->scroll_drag_timeout_id = 0;
518 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
520 ModestMsgEditWindowPrivate *priv;
523 GdkRectangle rectangle;
529 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
531 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
534 insert = gtk_text_buffer_get_insert (priv->text_buffer);
535 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
537 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
538 vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll));
539 offset = priv->msg_body->allocation.y;
541 new_value = vadj->value;
543 if ((offset + rectangle.y + rectangle.height) >
544 ((gint) (vadj->value +vadj->page_size))) {
545 new_value = (offset + rectangle.y) - vadj->page_size * 0.25;
546 if (new_value > vadj->upper - vadj->page_size)
547 new_value = vadj->upper - vadj->page_size;
548 } else if ((offset + rectangle.y) < ((gint) vadj->value)) {
549 new_value = (offset + rectangle.y - vadj->page_size * 0.75);
550 if (((gint) (new_value + vadj->page_size)) < (offset + rectangle.y + rectangle.height))
551 new_value = offset + rectangle.y + rectangle.height - (gint) vadj->page_size;
554 if (new_value > vadj->value)
555 new_value = vadj->value;
558 if (vadj->value != new_value) {
559 g_signal_emit_by_name (GTK_TEXT_VIEW(priv->msg_body)->layout,
561 vadj->value = new_value;
562 gtk_adjustment_value_changed (vadj);
563 /* invalidate body */
564 window = gtk_widget_get_parent_window (priv->msg_body);
566 gdk_window_invalidate_rect (window, NULL, TRUE);
572 correct_scroll (ModestMsgEditWindow *w)
574 ModestMsgEditWindowPrivate *priv;
576 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
577 if (gtk_grab_get_current () == priv->msg_body) {
578 if (priv->scroll_drag_timeout_id == 0) {
579 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
585 correct_scroll_without_drag_check (w, TRUE);
589 text_buffer_end_user_action (GtkTextBuffer *buffer,
590 ModestMsgEditWindow *userdata)
593 correct_scroll (userdata);
597 text_buffer_mark_set (GtkTextBuffer *buffer,
600 ModestMsgEditWindow *userdata)
602 gtk_text_buffer_begin_user_action (buffer);
603 gtk_text_buffer_end_user_action (buffer);
607 cut_clipboard_check (GtkTextView *text_view,
610 GtkTextBuffer *buffer;
612 buffer = gtk_text_view_get_buffer (text_view);
613 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
614 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
619 copy_clipboard_check (GtkTextView *text_view,
622 GtkTextBuffer *buffer;
624 buffer = gtk_text_view_get_buffer (text_view);
625 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
626 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
631 vadj_changed (GtkAdjustment *adj,
632 ModestMsgEditWindow *window)
634 ModestMsgEditWindowPrivate *priv;
636 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
638 if (priv->last_upper != adj->upper) {
639 priv->last_upper = adj->upper;
640 correct_scroll (window);
645 attachment_deleted (ModestAttachmentsView *attachments_view,
648 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
653 connect_signals (ModestMsgEditWindow *obj)
655 ModestMsgEditWindowPrivate *priv;
657 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
659 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
660 G_CALLBACK (text_buffer_refresh_attributes), obj);
661 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
662 G_CALLBACK (text_buffer_can_undo), obj);
663 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
664 G_CALLBACK (text_buffer_can_redo), obj);
665 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
666 G_CALLBACK (body_changed), obj);
667 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
668 G_CALLBACK (body_changed), obj);
669 g_signal_connect (G_OBJECT (obj), "window-state-event",
670 G_CALLBACK (modest_msg_edit_window_window_state_event),
672 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
673 G_CALLBACK (text_buffer_end_user_action), obj);
674 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
675 G_CALLBACK (text_buffer_mark_set), obj);
676 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
677 G_CALLBACK (text_buffer_apply_tag), obj);
678 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
679 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
680 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
681 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
682 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
683 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
685 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
686 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
688 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
689 G_CALLBACK (msg_body_focus), obj);
690 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
691 G_CALLBACK (msg_body_focus), obj);
692 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
693 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
694 "changed", G_CALLBACK (recpt_field_changed), obj);
695 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
696 "changed", G_CALLBACK (recpt_field_changed), obj);
697 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
698 "changed", G_CALLBACK (recpt_field_changed), obj);
699 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
700 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
701 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
703 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
704 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
706 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
708 G_CALLBACK (vadj_changed),
711 priv->clipboard_change_handler_id =
712 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
713 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
714 priv->default_clipboard_change_handler_id =
715 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
716 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
718 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
719 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
720 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
724 init_window (ModestMsgEditWindow *obj)
726 GtkWidget *to_caption, *subject_caption;
727 GtkWidget *main_vbox;
728 ModestMsgEditWindowPrivate *priv;
729 GtkActionGroup *action_group;
730 ModestWindowPrivate *parent_priv;
731 GdkPixbuf *window_icon = NULL;
732 GError *error = NULL;
734 GtkSizeGroup *size_group;
735 GtkWidget *subject_box;
736 GtkWidget *attachment_icon;
737 GtkWidget *window_box;
738 #if (GTK_MINOR_VERSION >= 10)
739 GdkAtom deserialize_type;
742 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
743 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
745 parent_priv->ui_manager = gtk_ui_manager_new();
746 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
747 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
749 /* Add common actions */
750 gtk_action_group_add_actions (action_group,
751 modest_msg_edit_action_entries,
752 G_N_ELEMENTS (modest_msg_edit_action_entries),
754 gtk_action_group_add_toggle_actions (action_group,
755 modest_msg_edit_toggle_action_entries,
756 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
758 gtk_action_group_add_radio_actions (action_group,
759 modest_msg_edit_alignment_radio_action_entries,
760 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
762 G_CALLBACK (modest_ui_actions_on_change_justify),
764 gtk_action_group_add_radio_actions (action_group,
765 modest_msg_edit_priority_action_entries,
766 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
768 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
770 gtk_action_group_add_radio_actions (action_group,
771 modest_msg_edit_file_format_action_entries,
772 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
773 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
774 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
776 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
777 g_object_unref (action_group);
779 /* Load the UI definition */
780 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
783 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
784 g_clear_error (&error);
787 /* Add accelerators */
788 gtk_window_add_accel_group (GTK_WINDOW (obj),
789 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
791 parent_priv->menubar = NULL;
793 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
795 /* Note: This ModestPairList* must exist for as long as the picker
796 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
797 * so it can't know how to manage its memory. */
798 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
799 MODEST_EDITABLE_ARRANGEMENT,
801 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 0.0);
802 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
803 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
805 priv->to_field = modest_recpt_editor_new ();
806 priv->cc_field = modest_recpt_editor_new ();
807 priv->bcc_field = modest_recpt_editor_new ();
808 subject_box = gtk_hbox_new (FALSE, 0);
809 priv->priority_icon = gtk_image_new ();
810 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
811 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
812 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
813 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
814 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
815 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
816 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
817 priv->add_attachment_button = gtk_button_new ();
818 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
819 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
820 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
821 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 0.5);
822 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
823 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
824 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
825 priv->attachments_view = modest_attachments_view_new (NULL);
827 priv->header_box = gtk_vbox_new (FALSE, 0);
829 hildon_button_add_title_size_group (HILDON_BUTTON (priv->from_field), size_group);
830 to_caption = modest_maemo_utils_create_captioned (size_group, _("mail_va_to"), priv->to_field);
831 priv->cc_caption = modest_maemo_utils_create_captioned (size_group, _("mail_va_cc"), priv->cc_field);
832 priv->bcc_caption = modest_maemo_utils_create_captioned (size_group, _("mail_va_hotfix1"), priv->bcc_field);
833 subject_caption = modest_maemo_utils_create_captioned (size_group, _("mail_va_subject"), subject_box);
834 priv->attachments_caption = modest_maemo_utils_create_captioned (size_group, _("mail_va_attachment"), priv->attachments_view);
835 g_object_unref (size_group);
837 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
838 hildon_button_add_value_size_group (HILDON_BUTTON (priv->from_field), size_group);
839 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
840 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
841 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
842 gtk_size_group_add_widget (size_group, priv->subject_field);
843 gtk_size_group_add_widget (size_group, priv->attachments_view);
844 g_object_unref (size_group);
846 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
847 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
848 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
849 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
850 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
851 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
852 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
855 priv->msg_body = wp_text_view_new ();
856 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
857 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
858 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
859 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
860 #if (GTK_MINOR_VERSION >= 10)
861 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
862 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
864 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
865 deserialize_type, TRUE);
867 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
869 priv->find_toolbar = hildon_find_toolbar_new (NULL);
870 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
872 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
874 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
875 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
876 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
877 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
879 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
881 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
882 priv->frame = gtk_frame_new (NULL);
883 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
885 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
886 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
887 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
889 window_box = gtk_vbox_new (FALSE, 0);
890 gtk_container_add (GTK_CONTAINER(obj), window_box);
892 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
894 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
896 /* Set window icon */
897 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
899 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
900 g_object_unref (window_icon);
905 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
907 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
909 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
910 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
911 priv->clipboard_change_handler_id))
912 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
913 priv->clipboard_change_handler_id);
914 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
915 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
916 priv->default_clipboard_change_handler_id))
917 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
918 priv->default_clipboard_change_handler_id);
920 if (priv->account_removed_handler_id &&
921 g_signal_handler_is_connected (modest_runtime_get_account_store (),
922 priv->account_removed_handler_id))
923 g_signal_handler_disconnect(modest_runtime_get_account_store (),
924 priv->account_removed_handler_id);
928 modest_msg_edit_window_finalize (GObject *obj)
930 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
932 /* Sanity check: shouldn't be needed, the window mgr should
933 call this function before */
934 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
936 if (priv->font_dialog != NULL) {
937 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
940 if (priv->clipboard_text != NULL) {
941 g_free (priv->clipboard_text);
942 priv->clipboard_text = NULL;
945 if (priv->draft_msg != NULL) {
946 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
947 if (TNY_IS_HEADER (header)) {
948 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
949 modest_window_mgr_unregister_header (mgr, header);
951 g_object_unref (priv->draft_msg);
952 priv->draft_msg = NULL;
954 if (priv->outbox_msg != NULL) {
955 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
956 if (TNY_IS_HEADER (header)) {
957 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
958 modest_window_mgr_unregister_header (mgr, header);
960 g_object_unref (priv->outbox_msg);
961 priv->outbox_msg = NULL;
963 if (priv->scroll_drag_timeout_id > 0) {
964 g_source_remove (priv->scroll_drag_timeout_id);
965 priv->scroll_drag_timeout_id = 0;
967 if (priv->clipboard_owner_idle > 0) {
968 g_source_remove (priv->clipboard_owner_idle);
969 priv->clipboard_owner_idle = 0;
971 if (priv->original_account_name)
972 g_free (priv->original_account_name);
973 g_free (priv->msg_uid);
974 g_free (priv->last_search);
975 g_slist_free (priv->font_items_group);
976 g_slist_free (priv->size_items_group);
977 g_object_unref (priv->attachments);
978 g_object_unref (priv->images);
980 /* This had to stay alive for as long as the picker that used it: */
981 modest_pair_list_free (priv->from_field_protos);
983 G_OBJECT_CLASS(parent_class)->finalize (obj);
987 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
989 GdkPixbufLoader *loader;
995 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
997 if (loader == NULL) {
1003 tny_stream_reset (TNY_STREAM (stream));
1004 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1005 GError *error = NULL;
1006 unsigned char read_buffer[128];
1008 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1010 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1012 g_error_free (error);
1017 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1019 g_object_ref (pixbuf);
1020 gdk_pixbuf_loader_close (loader, NULL);
1021 g_object_unref (loader);
1026 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1027 GdkPixbuf *new_pixbuf;
1029 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1030 gdk_pixbuf_get_width (pixbuf);
1031 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1032 g_object_unref (pixbuf);
1033 pixbuf = new_pixbuf;
1037 *stream_size = size;
1043 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1045 ModestMsgEditWindowPrivate *priv;
1048 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1050 for (iter = tny_list_create_iterator (attachments);
1051 !tny_iterator_is_done (iter);
1052 tny_iterator_next (iter)) {
1053 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1054 const gchar *cid = tny_mime_part_get_content_id (part);
1055 const gchar *mime_type = tny_mime_part_get_content_type (part);
1056 if ((cid != NULL)&&(mime_type != NULL)) {
1057 guint64 stream_size;
1058 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1059 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1062 g_object_unref (stream);
1064 if (pixbuf != NULL) {
1065 priv->images_count ++;
1066 priv->images_size += stream_size;
1067 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1068 g_object_unref (pixbuf);
1071 g_object_unref (part);
1073 g_object_unref (iter);
1077 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1079 TnyMimePart *parent = NULL;
1080 const gchar *content_type = NULL;
1081 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1083 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1085 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1086 parent = g_object_ref (msg);
1087 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1088 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1091 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1092 iter = tny_list_create_iterator (parts);
1093 while (!tny_iterator_is_done (iter)) {
1095 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1096 content_type = tny_mime_part_get_content_type (part);
1097 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1101 g_object_unref (part);
1103 tny_iterator_next (iter);
1105 g_object_unref (iter);
1106 g_object_unref (parts);
1109 if (parent != NULL) {
1110 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1113 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1114 iter = tny_list_create_iterator (parts);
1115 while (!tny_iterator_is_done (iter)) {
1117 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1118 content_type = tny_mime_part_get_content_type (part);
1119 if (content_type && g_str_has_prefix (content_type, "image/")) {
1120 tny_list_prepend (priv->images, (GObject *) part);
1122 g_object_unref (part);
1123 tny_iterator_next (iter);
1125 g_object_unref (iter);
1126 g_object_unref (parts);
1127 g_object_unref (parent);
1132 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1135 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1137 for (iter = tny_list_create_iterator (attachments) ;
1138 !tny_iterator_is_done (iter);
1139 tny_iterator_next (iter)) {
1140 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1141 const gchar *cid = tny_mime_part_get_content_id (part);
1143 char *invalid = NULL;
1144 gint int_cid = strtol (cid, &invalid, 10);
1145 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1146 priv->next_cid = int_cid + 1;
1149 g_object_unref (part);
1151 g_object_unref (iter);
1155 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1158 gchar *to, *cc, *bcc, *subject;
1160 ModestMsgEditWindowPrivate *priv;
1162 TnyHeaderFlags priority_flags;
1163 TnyFolder *msg_folder;
1164 gboolean is_html = FALSE;
1166 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1167 g_return_if_fail (TNY_IS_MSG (msg));
1169 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1171 header = tny_msg_get_header (msg);
1172 to = tny_header_dup_to (header);
1173 cc = tny_header_dup_cc (header);
1174 bcc = tny_header_dup_bcc (header);
1175 subject = tny_header_dup_subject (header);
1176 priority_flags = tny_header_get_priority (header);
1179 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1181 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1182 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1183 gtk_widget_show (priv->cc_caption);
1184 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1185 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1186 gtk_widget_hide (priv->cc_caption);
1189 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1190 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1191 gtk_widget_show (priv->bcc_caption);
1192 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1193 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1194 gtk_widget_hide (priv->bcc_caption);
1197 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1198 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1201 update_window_title (self);
1203 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1204 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1206 if ((body == NULL)||(body[0] == '\0')) {
1208 body = modest_text_utils_convert_to_html ("");
1211 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1212 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1215 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1218 /* Add attachments to the view */
1219 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1220 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1221 if (tny_list_get_length (priv->attachments) == 0) {
1222 gtk_widget_hide (priv->attachments_caption);
1224 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1225 gtk_widget_show_all (priv->attachments_caption);
1227 get_related_images (self, msg);
1228 update_next_cid (self, priv->attachments);
1229 update_next_cid (self, priv->images);
1230 replace_with_images (self, priv->images);
1232 if (preserve_is_rich && !is_html) {
1233 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1234 /* Get the default format required from configuration */
1235 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1236 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1239 /* Set the default focus depending on having already a To: field or not */
1240 if ((!to)||(*to == '\0')) {
1241 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1243 gtk_widget_grab_focus (priv->msg_body);
1246 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1248 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1249 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1251 modest_msg_edit_window_set_modified (self, FALSE);
1253 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1254 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1255 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1256 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1258 if (priv->msg_uid) {
1259 g_free (priv->msg_uid);
1260 priv->msg_uid = NULL;
1263 /* we should set a reference to the incoming message if it is a draft */
1264 msg_folder = tny_msg_get_folder (msg);
1266 if (modest_tny_folder_is_local_folder (msg_folder)) {
1267 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1268 if (type == TNY_FOLDER_TYPE_INVALID)
1269 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1271 if (type == TNY_FOLDER_TYPE_DRAFTS)
1272 priv->draft_msg = g_object_ref(msg);
1273 if (type == TNY_FOLDER_TYPE_OUTBOX)
1274 priv->outbox_msg = g_object_ref(msg);
1275 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1277 g_object_unref (msg_folder);
1287 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1290 GList *item_children, *node;
1291 GtkWidget *bin_child;
1293 bin_child = gtk_bin_get_child (GTK_BIN(item));
1295 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1297 for (node = item_children; node != NULL; node = g_list_next (node)) {
1298 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1299 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1302 g_list_free (item_children);
1306 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1309 GList *item_children, *node;
1311 box = gtk_bin_get_child (GTK_BIN (item));
1312 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1313 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1315 for (node = item_children; node != NULL; node = g_list_next (node)) {
1316 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1317 if (GTK_IS_TOGGLE_BUTTON (node->data))
1318 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1319 else if (GTK_IS_BUTTON (node->data))
1320 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1322 g_list_free (item_children);
1327 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1329 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1330 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1331 GtkWidget *placeholder;
1332 GtkWidget *tool_item;
1337 GtkWidget *sizes_menu;
1338 GtkWidget *fonts_menu;
1339 GSList *radio_group = NULL;
1340 GSList *node = NULL;
1344 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1345 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1347 /* Font color placeholder */
1348 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1349 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1352 tool_item = GTK_WIDGET (gtk_tool_item_new ());
1353 priv->font_color_button = hildon_color_button_new ();
1354 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1355 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1356 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
1357 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1358 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1359 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1360 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1362 G_CALLBACK (modest_msg_edit_window_color_button_change),
1365 /* Font size and face placeholder */
1366 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1367 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1369 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1370 priv->size_tool_button_label = gtk_label_new (NULL);
1371 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1372 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1373 size_text,"</span>", NULL);
1374 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1376 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1377 sizes_menu = gtk_menu_new ();
1378 priv->size_items_group = NULL;
1380 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1381 GtkWidget *size_menu_item;
1383 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1384 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1385 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1386 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1387 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1388 gtk_widget_show (size_menu_item);
1390 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1394 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1395 GtkWidget *item = (GtkWidget *) node->data;
1396 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1400 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1401 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1402 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1403 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1404 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1405 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1406 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1407 priv->font_size_toolitem = tool_item;
1410 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1411 priv->font_tool_button_label = gtk_label_new (NULL);
1412 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1413 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1415 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1416 fonts_menu = gtk_menu_new ();
1417 priv->font_items_group = NULL;
1419 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1420 GtkWidget *font_menu_item;
1421 GtkWidget *child_label;
1423 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1424 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1425 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1426 wp_get_font_name (font_index), "</span>", NULL);
1427 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1430 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1431 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1432 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1433 gtk_widget_show (font_menu_item);
1435 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1438 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1439 GtkWidget *item = (GtkWidget *) node->data;
1440 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1443 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1444 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1445 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1446 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1447 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1448 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1449 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1450 priv->font_face_toolitem = tool_item;
1452 /* Set expand and homogeneous for remaining items */
1453 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1454 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1455 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1456 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1457 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1458 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1459 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1460 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1461 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1463 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1464 will not show the tool items added to the placeholders) */
1465 gtk_widget_show_all (parent_priv->toolbar);
1467 /* Set the no show all *after* showing all items. We do not
1468 want the toolbar to be shown with a show all because it
1469 could go agains the gconf setting regarding showing or not
1470 the toolbar of the editor window */
1471 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1477 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1480 ModestWindowPrivate *parent_priv;
1481 ModestMsgEditWindowPrivate *priv;
1482 ModestDimmingRulesGroup *menu_rules_group = NULL;
1483 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1484 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1485 ModestWindowMgr *mgr = NULL;
1487 g_return_val_if_fail (msg, NULL);
1488 g_return_val_if_fail (account_name, NULL);
1490 mgr = modest_runtime_get_window_mgr ();
1492 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1494 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1495 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1497 /* Menubar. Update the state of some toggles */
1498 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1499 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1500 priv->from_field_protos = get_transports ();
1501 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1502 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1503 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1505 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1506 hildon_touch_selector_get_current_text
1507 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1508 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1509 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1512 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1514 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1516 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1518 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1520 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1521 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1522 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1523 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1524 /* Add common dimming rules */
1525 modest_dimming_rules_group_add_rules (menu_rules_group,
1526 modest_msg_edit_window_menu_dimming_entries,
1527 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1528 MODEST_WINDOW (obj));
1529 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1530 modest_msg_edit_window_toolbar_dimming_entries,
1531 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1532 MODEST_WINDOW (obj));
1533 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1534 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1535 MODEST_WINDOW (obj));
1536 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1537 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1538 MODEST_WINDOW (obj));
1539 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1540 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1541 MODEST_WINDOW (obj));
1542 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1543 modest_msg_edit_window_clipboard_dimming_entries,
1544 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1545 MODEST_WINDOW (obj));
1546 /* Insert dimming rules group for this window */
1547 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1548 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1549 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1550 /* Checks the dimming rules */
1551 g_object_unref (menu_rules_group);
1552 g_object_unref (toolbar_rules_group);
1553 g_object_unref (clipboard_rules_group);
1554 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1556 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1558 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1559 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1560 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1561 priv->update_caption_visibility = TRUE;
1563 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1565 /* Track account-removed signal, this window should be closed
1566 in the case we're creating a mail associated to the account
1568 priv->account_removed_handler_id =
1569 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1571 G_CALLBACK(on_account_removed),
1574 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1576 return (ModestWindow*) obj;
1580 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1582 GString **string_buffer = (GString **) user_data;
1584 *string_buffer = g_string_append (*string_buffer, buffer);
1590 * @result: A new string which should be freed with g_free().
1593 get_formatted_data (ModestMsgEditWindow *edit_window)
1595 ModestMsgEditWindowPrivate *priv;
1596 GString *string_buffer = g_string_new ("");
1598 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1600 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1602 modest_text_utils_hyperlinkify (string_buffer);
1604 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1606 return g_string_free (string_buffer, FALSE);
1611 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1614 const gchar *account_name;
1615 ModestMsgEditWindowPrivate *priv;
1616 TnyIterator *att_iter;
1618 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1620 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1622 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1623 g_return_val_if_fail (account_name, NULL);
1626 /* don't free these (except from) */
1627 data = g_slice_new0 (MsgData);
1628 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1630 data->account_name = g_strdup (account_name);
1631 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1632 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1633 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1634 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1635 if (priv->draft_msg) {
1636 data->draft_msg = g_object_ref (priv->draft_msg);
1637 } else if (priv->outbox_msg) {
1638 data->draft_msg = g_object_ref (priv->outbox_msg);
1640 data->draft_msg = NULL;
1643 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1645 gtk_text_buffer_get_bounds (buf, &b, &e);
1646 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1648 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1649 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1651 data->html_body = NULL;
1653 /* deep-copy the data */
1654 att_iter = tny_list_create_iterator (priv->attachments);
1655 data->attachments = NULL;
1656 while (!tny_iterator_is_done (att_iter)) {
1657 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1658 if (!(TNY_IS_MIME_PART(part))) {
1659 g_warning ("strange data in attachment list");
1660 g_object_unref (part);
1661 tny_iterator_next (att_iter);
1664 data->attachments = g_list_append (data->attachments,
1666 tny_iterator_next (att_iter);
1668 g_object_unref (att_iter);
1670 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1671 att_iter = tny_list_create_iterator (priv->images);
1672 data->images = NULL;
1673 while (!tny_iterator_is_done (att_iter)) {
1674 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1676 if (!(TNY_IS_MIME_PART(part))) {
1677 g_warning ("strange data in attachment list");
1678 g_object_unref (part);
1679 tny_iterator_next (att_iter);
1682 cid = tny_mime_part_get_content_id (part);
1684 gchar *image_tag_id;
1685 GtkTextTag *image_tag;
1687 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1688 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1689 g_free (image_tag_id);
1691 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1693 ((gtk_text_iter_has_tag (&iter, image_tag))||
1694 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1695 data->images = g_list_append (data->images,
1696 g_object_ref (part));
1698 g_object_unref (part);
1699 tny_iterator_next (att_iter);
1701 g_object_unref (att_iter);
1703 data->priority_flags = priv->priority_flags;
1710 unref_gobject (GObject *obj, gpointer data)
1712 if (!G_IS_OBJECT(obj))
1714 g_object_unref (obj);
1718 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1721 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1729 g_free (data->from);
1730 g_free (data->subject);
1731 g_free (data->plain_body);
1732 g_free (data->html_body);
1733 g_free (data->account_name);
1735 if (data->draft_msg != NULL) {
1736 g_object_unref (data->draft_msg);
1737 data->draft_msg = NULL;
1740 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1741 g_list_free (data->attachments);
1742 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1743 g_list_free (data->images);
1745 g_slice_free (MsgData, data);
1749 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1751 guint64 *parts_size)
1753 ModestMsgEditWindowPrivate *priv;
1755 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1757 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1759 /* TODO: add images */
1760 *parts_size += priv->images_size;
1761 *parts_count += priv->images_count;
1766 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1769 ModestMsgEditWindowPrivate *priv = NULL;
1770 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1772 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1774 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1776 return MODEST_MSG_EDIT_FORMAT_HTML;
1778 return MODEST_MSG_EDIT_FORMAT_TEXT;
1782 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1783 ModestMsgEditFormat format)
1785 ModestMsgEditWindowPrivate *priv;
1787 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1788 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1791 case MODEST_MSG_EDIT_FORMAT_HTML:
1792 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1794 case MODEST_MSG_EDIT_FORMAT_TEXT:
1795 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1798 g_return_if_reached ();
1802 ModestMsgEditFormatState *
1803 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1805 ModestMsgEditFormatState *format_state = NULL;
1806 ModestMsgEditWindowPrivate *priv;
1807 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1809 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1810 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1812 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1814 format_state = g_new0 (ModestMsgEditFormatState, 1);
1815 format_state->bold = buffer_format->bold&0x1;
1816 format_state->italics = buffer_format->italic&0x1;
1817 format_state->bullet = buffer_format->bullet&0x1;
1818 format_state->color = buffer_format->color;
1819 format_state->font_size = buffer_format->font_size;
1820 format_state->font_family = wp_get_font_name (buffer_format->font);
1821 format_state->justification = buffer_format->justification;
1822 g_free (buffer_format);
1824 return format_state;
1829 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1830 const ModestMsgEditFormatState *format_state)
1832 ModestMsgEditWindowPrivate *priv;
1833 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1834 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1835 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1836 g_return_if_fail (format_state != NULL);
1838 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1839 gtk_widget_grab_focus (priv->msg_body);
1840 buffer_format->bold = (format_state->bold != FALSE);
1841 buffer_format->italic = (format_state->italics != FALSE);
1842 buffer_format->color = format_state->color;
1843 buffer_format->font_size = format_state->font_size;
1844 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1845 buffer_format->justification = format_state->justification;
1846 buffer_format->bullet = format_state->bullet;
1848 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1850 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1851 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1852 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1853 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1854 buffer_format->cs.font = (buffer_format->font != current_format->font);
1855 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1856 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1858 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1859 if (buffer_format->cs.bold) {
1860 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1861 GINT_TO_POINTER (buffer_format->bold&0x1));
1863 if (buffer_format->cs.italic) {
1864 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1865 GINT_TO_POINTER (buffer_format->italic&0x1));
1867 if (buffer_format->cs.color) {
1868 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1869 GINT_TO_POINTER (&(buffer_format->color)));
1871 if (buffer_format->cs.font_size) {
1872 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1873 GINT_TO_POINTER (buffer_format->font_size));
1875 if (buffer_format->cs.justification) {
1876 switch (buffer_format->justification) {
1877 case GTK_JUSTIFY_LEFT:
1878 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1879 GINT_TO_POINTER(TRUE));
1881 case GTK_JUSTIFY_CENTER:
1882 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1883 GINT_TO_POINTER(TRUE));
1885 case GTK_JUSTIFY_RIGHT:
1886 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1887 GINT_TO_POINTER(TRUE));
1894 if (buffer_format->cs.font) {
1895 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1896 GINT_TO_POINTER (buffer_format->font));
1898 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1899 if (buffer_format->cs.bullet) {
1900 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1901 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1903 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1905 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1907 g_free (buffer_format);
1908 g_free (current_format);
1910 /* Check dimming rules */
1911 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1912 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1916 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1918 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1920 ModestWindowPrivate *parent_priv;
1921 ModestMsgEditWindowPrivate *priv;
1922 GtkWidget *new_size_menuitem;
1923 GtkWidget *new_font_menuitem;
1925 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1926 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1928 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1929 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1930 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1931 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1933 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1934 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1935 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1938 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1940 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1941 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1943 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1944 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1946 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1947 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1950 switch (buffer_format->justification)
1952 case GTK_JUSTIFY_LEFT:
1953 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1955 case GTK_JUSTIFY_CENTER:
1956 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1958 case GTK_JUSTIFY_RIGHT:
1959 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1966 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1968 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1969 G_CALLBACK (modest_msg_edit_window_color_button_change),
1971 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1972 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1973 G_CALLBACK (modest_msg_edit_window_color_button_change),
1976 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1977 buffer_format->font_size))->data);
1978 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1982 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1983 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1984 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1986 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1987 G_CALLBACK (modest_msg_edit_window_size_change),
1989 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1990 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1991 G_CALLBACK (modest_msg_edit_window_size_change),
1995 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1996 buffer_format->font))->data);
1997 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
2001 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2002 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2003 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2005 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2006 G_CALLBACK (modest_msg_edit_window_font_change),
2008 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2009 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2010 G_CALLBACK (modest_msg_edit_window_font_change),
2014 g_free (buffer_format);
2018 #ifdef MODEST_HILDON_VERSION_0
2020 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2023 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2024 ModestMsgEditWindowPrivate *priv;
2025 GtkWidget *dialog = NULL;
2027 GdkColor *new_color = NULL;
2029 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2030 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2032 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2033 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2034 g_free (buffer_format);
2036 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2037 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2038 if (new_color != NULL) {
2039 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2040 (gpointer) new_color);
2043 gtk_widget_destroy (dialog);
2048 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2051 ModestMsgEditWindowPrivate *priv;
2052 GtkWidget *dialog = NULL;
2054 GdkColor *old_color = NULL;
2055 const GdkColor *new_color = NULL;
2057 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2058 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2060 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2061 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2063 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2064 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2065 if (new_color != NULL)
2066 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2068 gtk_widget_destroy (dialog);
2074 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2077 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2078 ModestMsgEditWindowPrivate *priv;
2079 GtkWidget *dialog = NULL;
2081 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2082 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2084 dialog = hildon_color_chooser_new ();
2085 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2086 g_free (buffer_format);
2088 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2090 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2091 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2094 gtk_widget_destroy (dialog);
2099 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2102 ModestMsgEditWindowPrivate *priv;
2103 GtkWidget *dialog = NULL;
2104 GdkColor *old_color = NULL;
2106 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2107 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2109 dialog = hildon_color_chooser_new ();
2110 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2112 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2114 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2115 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2117 gtk_widget_destroy (dialog);
2120 #endif /*!MODEST_HILDON_VERSION_0*/
2125 create_stream_for_uri (const gchar* uri)
2130 TnyStream *result = NULL;
2132 GnomeVFSHandle *handle = NULL;
2133 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2134 if (test == GNOME_VFS_OK) {
2135 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2136 /* Streams over OBEX (Bluetooth) are not seekable but
2137 * we expect them to be (we might need to read them
2138 * several times). So if this is a Bluetooth URI just
2139 * read the whole file into memory (this is not a fast
2140 * protocol so we can assume that these files are not
2141 * going to be very big) */
2142 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2143 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2144 TnyStream *memstream = tny_camel_mem_stream_new ();
2145 tny_stream_write_to_stream (vfssstream, memstream);
2146 g_object_unref (vfssstream);
2149 result = vfssstream;
2157 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2160 ModestMsgEditWindowPrivate *priv;
2161 GtkWidget *dialog = NULL;
2163 GSList *uris = NULL;
2164 GSList *uri_node = NULL;
2166 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2168 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2169 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2170 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2172 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2174 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2175 GTK_WINDOW (dialog), GTK_WINDOW (window));
2177 response = gtk_dialog_run (GTK_DIALOG (dialog));
2179 case GTK_RESPONSE_OK:
2180 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2185 gtk_widget_destroy (dialog);
2187 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2189 GnomeVFSHandle *handle = NULL;
2190 GnomeVFSResult result;
2191 GtkTextIter position;
2192 GtkTextMark *insert_mark;
2194 uri = (const gchar *) uri_node->data;
2195 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2196 if (result == GNOME_VFS_OK) {
2198 GnomeVFSFileInfo *info;
2199 gchar *filename, *basename, *escaped_filename;
2200 TnyMimePart *mime_part;
2202 const gchar *mime_type = NULL;
2203 GnomeVFSURI *vfs_uri;
2204 guint64 stream_size;
2206 gnome_vfs_close (handle);
2207 vfs_uri = gnome_vfs_uri_new (uri);
2209 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2210 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2211 g_free (escaped_filename);
2212 gnome_vfs_uri_unref (vfs_uri);
2213 info = gnome_vfs_file_info_new ();
2215 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2216 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2218 mime_type = gnome_vfs_file_info_get_mime_type (info);
2220 mime_part = tny_platform_factory_new_mime_part
2221 (modest_runtime_get_platform_factory ());
2223 TnyStream *stream = create_stream_for_uri (uri);
2225 if (stream == NULL) {
2227 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2229 g_object_unref (mime_part);
2230 gnome_vfs_file_info_unref (info);
2234 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2236 content_id = g_strdup_printf ("%d", priv->next_cid);
2237 tny_mime_part_set_content_id (mime_part, content_id);
2238 g_free (content_id);
2241 basename = g_path_get_basename (filename);
2242 tny_mime_part_set_filename (mime_part, basename);
2245 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2247 if (pixbuf != NULL) {
2248 priv->images_size += stream_size;
2249 priv->images_count ++;
2250 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2251 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2252 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2255 tny_list_prepend (priv->images, (GObject *) mime_part);
2256 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2258 g_object_unref (mime_part);
2259 gnome_vfs_file_info_unref (info);
2268 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2270 GtkWidget *dialog = NULL;
2272 GSList *uris = NULL;
2274 GnomeVFSFileSize total_size, allowed_size;
2275 ModestMsgEditWindowPrivate *priv;
2279 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2281 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2283 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2286 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2287 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2288 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2289 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), GTK_WINDOW (window));
2291 response = gtk_dialog_run (GTK_DIALOG (dialog));
2293 case GTK_RESPONSE_OK:
2294 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2299 gtk_widget_destroy (dialog);
2301 /* allowed size is the maximum size - what's already there */
2302 modest_attachments_view_get_sizes (
2303 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2304 &att_num, &att_size);
2305 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2308 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2310 const gchar *uri = (const gchar *) uri_node->data;
2312 total_size += modest_msg_edit_window_attach_file_one
2313 (window, uri, allowed_size);
2315 if (total_size > allowed_size) {
2316 g_warning ("%s: total size: %u",
2317 __FUNCTION__, (unsigned int)total_size);
2321 allowed_size -= total_size;
2325 g_slist_foreach (uris, (GFunc) g_free, NULL);
2326 g_slist_free (uris);
2331 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2333 GnomeVFSFileSize allowed_size)
2336 GnomeVFSHandle *handle = NULL;
2337 ModestMsgEditWindowPrivate *priv;
2338 GnomeVFSResult result;
2339 GnomeVFSFileSize size = 0;
2340 g_return_val_if_fail (window, 0);
2341 g_return_val_if_fail (uri, 0);
2343 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2345 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2346 if (result == GNOME_VFS_OK) {
2347 TnyMimePart *mime_part;
2349 const gchar *mime_type = NULL;
2351 gchar *escaped_filename;
2354 GnomeVFSFileInfo *info;
2355 GnomeVFSURI *vfs_uri;
2357 gnome_vfs_close (handle);
2358 vfs_uri = gnome_vfs_uri_new (uri);
2361 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2362 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2363 g_free (escaped_filename);
2364 gnome_vfs_uri_unref (vfs_uri);
2366 info = gnome_vfs_file_info_new ();
2368 if (gnome_vfs_get_file_info (uri,
2370 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2372 mime_type = gnome_vfs_file_info_get_mime_type (info);
2373 mime_part = tny_platform_factory_new_mime_part
2374 (modest_runtime_get_platform_factory ());
2376 /* try to get the attachment's size; this may fail for weird
2377 * file systems, like obex, upnp... */
2378 if (allowed_size != 0 &&
2379 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2381 if (size > allowed_size) {
2382 modest_platform_information_banner (NULL, NULL,
2383 dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2387 g_warning ("%s: could not get attachment size", __FUNCTION__);
2389 stream = create_stream_for_uri (uri);
2391 if (stream == NULL) {
2393 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2395 g_object_unref (mime_part);
2396 gnome_vfs_file_info_unref (info);
2400 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2401 g_object_unref (stream);
2403 content_id = g_strdup_printf ("%d", priv->next_cid);
2404 tny_mime_part_set_content_id (mime_part, content_id);
2405 g_free (content_id);
2408 basename = g_path_get_basename (filename);
2409 tny_mime_part_set_filename (mime_part, basename);
2412 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2413 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2415 info->size == 0, info->size);
2416 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2417 gtk_widget_show_all (priv->attachments_caption);
2418 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2420 g_object_unref (mime_part);
2421 gnome_vfs_file_info_unref (info);
2428 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2431 ModestMsgEditWindowPrivate *priv;
2434 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2435 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2437 if (att_list == NULL) {
2438 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2440 g_object_ref (att_list);
2443 if (tny_list_get_length (att_list) == 0) {
2444 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2446 gboolean dialog_response;
2447 gchar *message = NULL;
2448 gchar *filename = NULL;
2450 if (tny_list_get_length (att_list) == 1) {
2452 iter = tny_list_create_iterator (att_list);
2453 part = (TnyMimePart *) tny_iterator_get_current (iter);
2454 g_object_unref (iter);
2455 if (TNY_IS_MSG (part)) {
2456 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2458 filename = tny_header_dup_subject (header);
2459 g_object_unref (header);
2461 if (filename == NULL) {
2462 filename = g_strdup (_("mail_va_no_subject"));
2465 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2467 g_object_unref (part);
2469 filename = g_strdup ("");
2471 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2472 tny_list_get_length (att_list)), filename);
2475 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2478 if (dialog_response != GTK_RESPONSE_OK) {
2479 g_object_unref (att_list);
2482 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
2484 for (iter = tny_list_create_iterator (att_list);
2485 !tny_iterator_is_done (iter);
2486 tny_iterator_next (iter)) {
2487 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2488 const gchar *att_id;
2489 tny_list_remove (priv->attachments, (GObject *) mime_part);
2491 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2493 if (tny_list_get_length (priv->attachments) == 0)
2494 gtk_widget_hide (priv->attachments_caption);
2495 att_id = tny_mime_part_get_content_id (mime_part);
2497 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2499 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2500 g_object_unref (mime_part);
2502 g_object_unref (iter);
2505 g_object_unref (att_list);
2507 /* if the last attachment has been removed, focus the Subject: field */
2508 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2509 gtk_widget_grab_focus (priv->subject_field);
2513 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2516 ModestMsgEditWindowPrivate *priv;
2517 GdkColor *new_color;
2518 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2520 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2521 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2524 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2526 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2528 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2530 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2535 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2538 ModestMsgEditWindowPrivate *priv;
2539 gint new_size_index;
2540 ModestMsgEditWindow *window;
2543 window = MODEST_MSG_EDIT_WINDOW (userdata);
2544 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2545 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2547 if (gtk_check_menu_item_get_active (menu_item)) {
2549 WPTextBufferFormat format;
2551 memset (&format, 0, sizeof (format));
2552 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2554 label = gtk_bin_get_child (GTK_BIN (menu_item));
2556 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2557 format.cs.font_size = TRUE;
2558 format.cs.text_position = TRUE;
2559 format.cs.font = TRUE;
2560 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2561 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2563 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2564 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2565 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2567 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2568 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2569 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2575 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2578 ModestMsgEditWindowPrivate *priv;
2579 gint new_font_index;
2580 ModestMsgEditWindow *window;
2583 window = MODEST_MSG_EDIT_WINDOW (userdata);
2584 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2585 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2587 if (gtk_check_menu_item_get_active (menu_item)) {
2590 label = gtk_bin_get_child (GTK_BIN (menu_item));
2592 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2594 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2595 GINT_TO_POINTER(new_font_index)))
2596 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2598 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2599 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2600 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2606 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2608 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2609 ModestWindowPrivate *parent_priv;
2610 ModestWindowMgr *mgr;
2611 gboolean is_fullscreen;
2612 GtkAction *fs_toggle_action;
2615 mgr = modest_runtime_get_window_mgr ();
2616 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2618 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2620 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2621 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2622 if (is_fullscreen != active)
2623 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2631 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2634 ModestMsgEditWindowPrivate *priv = NULL;
2635 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2637 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2638 if (!priv->update_caption_visibility)
2641 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2643 gtk_widget_show (priv->cc_caption);
2645 gtk_widget_hide (priv->cc_caption);
2647 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2651 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2654 ModestMsgEditWindowPrivate *priv = NULL;
2655 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2657 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2658 if (!priv->update_caption_visibility)
2661 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2663 gtk_widget_show (priv->bcc_caption);
2665 gtk_widget_hide (priv->bcc_caption);
2667 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2671 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2672 ModestRecptEditor *editor)
2674 ModestMsgEditWindowPrivate *priv;
2676 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2677 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2679 /* we check for low-mem; in that case, show a warning, and don't allow
2680 * for the addressbook
2682 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2685 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2687 if (editor == NULL) {
2688 GtkWidget *view_focus;
2689 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2691 /* This code should be kept in sync with ModestRecptEditor. The
2692 textview inside the recpt editor is the one that really gets the
2693 focus. As it's inside a scrolled window, and this one inside the
2694 hbox recpt editor inherits from, we'll need to go up in the
2695 hierarchy to know if the text view is part of the recpt editor
2696 or if it's a different text entry */
2698 if (gtk_widget_get_parent (view_focus)) {
2699 GtkWidget *first_parent;
2701 first_parent = gtk_widget_get_parent (view_focus);
2702 if (gtk_widget_get_parent (first_parent) &&
2703 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2704 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2709 editor = MODEST_RECPT_EDITOR (priv->to_field);
2713 modest_address_book_select_addresses (editor);
2718 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2720 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2722 modest_msg_edit_window_open_addressbook (window, NULL);
2726 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2727 gboolean show_toolbar)
2729 ModestWindowPrivate *parent_priv;
2730 const gchar *action_name;
2733 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2734 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2736 /* We can not just use the code of
2737 modest_msg_edit_window_setup_toolbar because it has a
2738 mixture of both initialization and creation code. */
2740 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2742 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2744 /* Update also the actions (to update the toggles in the
2745 menus), we have to do it manually because some other window
2746 of the same time could have changed it (remember that the
2747 toolbar fullscreen mode is shared by all the windows of the
2749 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2750 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2752 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2754 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2755 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2761 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2762 TnyHeaderFlags priority_flags)
2764 ModestMsgEditWindowPrivate *priv;
2765 ModestWindowPrivate *parent_priv;
2767 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2769 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2770 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2772 if (priv->priority_flags != priority_flags) {
2773 GtkAction *priority_action = NULL;
2775 priv->priority_flags = priority_flags;
2777 switch (priority_flags) {
2778 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2779 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2780 gtk_widget_show (priv->priority_icon);
2781 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2782 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2784 case TNY_HEADER_FLAG_LOW_PRIORITY:
2785 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2786 gtk_widget_show (priv->priority_icon);
2787 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2788 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2791 gtk_widget_hide (priv->priority_icon);
2792 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2793 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2796 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2797 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2802 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2805 ModestMsgEditWindowPrivate *priv;
2806 ModestWindowPrivate *parent_priv;
2807 gint current_format;
2809 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2811 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2812 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2814 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2815 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2817 if (current_format != file_format) {
2818 switch (file_format) {
2819 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2820 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2821 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2823 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2827 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2828 response = gtk_dialog_run (GTK_DIALOG (dialog));
2829 gtk_widget_destroy (dialog);
2830 if (response == GTK_RESPONSE_OK) {
2831 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2833 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2834 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2839 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2840 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2841 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2846 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2849 ModestMsgEditWindowPrivate *priv;
2850 WPTextBufferFormat oldfmt, fmt;
2851 gint old_position = 0;
2855 GdkColor *color = NULL;
2856 gboolean bold, bold_set, italic, italic_set;
2857 gboolean underline, underline_set;
2858 gboolean strikethrough, strikethrough_set;
2859 gboolean position_set;
2860 gboolean font_size_set, font_set, color_set;
2863 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2864 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2866 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2867 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2868 GTK_WINDOW(dialog), GTK_WINDOW (window));
2870 /* First we get the currently selected font information */
2871 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2873 switch (oldfmt.text_position) {
2874 case TEXT_POSITION_NORMAL:
2877 case TEXT_POSITION_SUPERSCRIPT:
2885 g_object_set (G_OBJECT (dialog),
2886 "bold", oldfmt.bold != FALSE,
2887 "bold-set", !oldfmt.cs.bold,
2888 "underline", oldfmt.underline != FALSE,
2889 "underline-set", !oldfmt.cs.underline,
2890 "italic", oldfmt.italic != FALSE,
2891 "italic-set", !oldfmt.cs.italic,
2892 "strikethrough", oldfmt.strikethrough != FALSE,
2893 "strikethrough-set", !oldfmt.cs.strikethrough,
2894 "color", &oldfmt.color,
2895 "color-set", !oldfmt.cs.color,
2896 "size", wp_font_size[oldfmt.font_size],
2897 "size-set", !oldfmt.cs.font_size,
2898 "position", old_position,
2899 "position-set", !oldfmt.cs.text_position,
2900 "family", wp_get_font_name (oldfmt.font),
2901 "family-set", !oldfmt.cs.font,
2904 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2905 GTK_WINDOW (dialog), GTK_WINDOW (window));
2906 gtk_widget_show_all (dialog);
2907 priv->font_dialog = dialog;
2908 response = gtk_dialog_run (GTK_DIALOG (dialog));
2909 priv->font_dialog = NULL;
2910 if (response == GTK_RESPONSE_OK) {
2912 g_object_get( dialog,
2914 "bold-set", &bold_set,
2915 "underline", &underline,
2916 "underline-set", &underline_set,
2918 "italic-set", &italic_set,
2919 "strikethrough", &strikethrough,
2920 "strikethrough-set", &strikethrough_set,
2922 "color-set", &color_set,
2924 "size-set", &font_size_set,
2925 "family", &font_name,
2926 "family-set", &font_set,
2927 "position", &position,
2928 "position-set", &position_set,
2933 if (response == GTK_RESPONSE_OK) {
2934 memset(&fmt, 0, sizeof(fmt));
2940 fmt.italic = italic;
2941 fmt.cs.italic = TRUE;
2943 if (underline_set) {
2944 fmt.underline = underline;
2945 fmt.cs.underline = TRUE;
2947 if (strikethrough_set) {
2948 fmt.strikethrough = strikethrough;
2949 fmt.cs.strikethrough = TRUE;
2954 ? TEXT_POSITION_NORMAL
2955 : ( ( position == 1 )
2956 ? TEXT_POSITION_SUPERSCRIPT
2957 : TEXT_POSITION_SUBSCRIPT );
2958 fmt.cs.text_position = TRUE;
2959 fmt.font_size = oldfmt.font_size;
2963 fmt.cs.color = TRUE;
2966 fmt.font = wp_get_font_index(font_name,
2971 if (font_size_set) {
2972 fmt.cs.font_size = TRUE;
2973 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2975 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2976 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2978 gtk_widget_destroy (dialog);
2980 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2984 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2986 ModestMsgEditWindowPrivate *priv;
2988 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2989 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2991 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2993 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2994 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2998 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3000 ModestMsgEditWindowPrivate *priv;
3002 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3003 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3005 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3007 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3008 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3013 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3015 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3017 priv->can_undo = can_undo;
3021 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3023 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3025 priv->can_redo = can_redo;
3029 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3031 ModestMsgEditWindowPrivate *priv;
3032 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3033 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3035 return priv->can_undo;
3039 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3041 ModestMsgEditWindowPrivate *priv;
3042 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3043 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3045 return priv->can_redo;
3050 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3053 GtkTextIter match_start, match_end;
3055 if (image_id == NULL)
3058 gtk_text_buffer_get_start_iter (buffer, &iter);
3060 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3061 GSList *tags = gtk_text_iter_get_tags (&match_start);
3063 for (node = tags; node != NULL; node = g_slist_next (node)) {
3064 GtkTextTag *tag = (GtkTextTag *) node->data;
3065 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3066 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3067 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3069 offset = gtk_text_iter_get_offset (&match_start);
3070 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3071 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3075 gtk_text_iter_forward_char (&iter);
3080 message_is_empty (ModestMsgEditWindow *window)
3082 ModestMsgEditWindowPrivate *priv = NULL;
3084 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3085 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3087 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3088 * so we can ignore markup.
3090 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3093 count = gtk_text_buffer_get_char_count (buf);
3099 msg_body_focus (GtkWidget *focus,
3100 GdkEventFocus *event,
3104 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3105 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3106 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3111 recpt_field_changed (GtkTextBuffer *buffer,
3112 ModestMsgEditWindow *editor)
3114 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3115 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3119 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3121 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3122 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3126 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3129 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3130 GtkTextBuffer *buffer;
3132 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3133 gtk_text_buffer_set_modified (buffer, modified);
3134 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3135 gtk_text_buffer_set_modified (buffer, modified);
3136 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3137 gtk_text_buffer_set_modified (buffer, modified);
3138 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3142 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3144 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3145 const char *account_name;
3146 GtkTextBuffer *buffer;
3148 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3149 if (gtk_text_buffer_get_modified (buffer))
3151 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3152 if (gtk_text_buffer_get_modified (buffer))
3154 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3155 if (gtk_text_buffer_get_modified (buffer))
3157 if (gtk_text_buffer_get_modified (priv->text_buffer))
3159 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3160 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3171 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3173 ModestMsgEditWindowPrivate *priv = NULL;
3175 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3176 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3178 /* check if there's no recipient added */
3179 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3180 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3181 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3182 /* no recipient contents, then select contacts */
3183 modest_msg_edit_window_open_addressbook (window, NULL);
3187 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3188 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3191 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3192 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3195 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3196 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3200 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3201 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3202 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3209 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3210 ModestMsgEditWindow *window)
3212 modest_msg_edit_window_offer_attach_file (window);
3216 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3218 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3220 return priv->clipboard_text;
3224 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3226 ModestMsgEditWindow *window)
3228 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3229 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3231 if (!GTK_WIDGET_VISIBLE (window))
3234 g_object_ref (window);
3235 text = gtk_clipboard_wait_for_text (selection_clipboard);
3237 if (priv->clipboard_text != NULL) {
3238 g_free (priv->clipboard_text);
3240 priv->clipboard_text = text;
3242 if (GTK_WIDGET_VISIBLE (window)) {
3243 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3245 g_object_unref (window);
3248 static gboolean clipboard_owner_change_idle (gpointer userdata)
3250 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3251 ModestMsgEditWindowPrivate *priv;
3253 gdk_threads_enter ();
3254 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3255 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3257 priv->clipboard_owner_idle = 0;
3258 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3259 gdk_threads_leave ();
3265 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3267 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3268 if (priv->clipboard_owner_idle == 0) {
3269 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3274 subject_field_move_cursor (GtkEntry *entry,
3275 GtkMovementStep step,
3280 if (!GTK_WIDGET_VISIBLE (window))
3283 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3287 update_window_title (ModestMsgEditWindow *window)
3289 ModestMsgEditWindowPrivate *priv = NULL;
3290 const gchar *subject;
3292 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3293 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3294 if (subject == NULL || subject[0] == '\0')
3295 subject = _("mail_va_new_email");
3297 gtk_window_set_title (GTK_WINDOW (window), subject);
3302 subject_field_changed (GtkEditable *editable,
3303 ModestMsgEditWindow *window)
3305 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3306 update_window_title (window);
3307 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3308 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3309 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3313 subject_field_insert_text (GtkEditable *editable,
3315 gint new_text_length,
3317 ModestMsgEditWindow *window)
3319 GString *result = g_string_new ("");
3321 gint result_len = 0;
3322 const gchar *entry_text = NULL;
3325 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3326 old_length = g_utf8_strlen (entry_text, -1);
3328 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3329 gunichar c = g_utf8_get_char_validated (current, 8);
3330 /* Invalid unichar, stop */
3336 result = g_string_append_unichar (result, c);
3340 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3341 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3344 /* Prevent endless recursion */
3345 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3346 g_signal_emit_by_name (editable, "insert-text",
3347 (gpointer) result->str, (gpointer) result->len,
3348 (gpointer) position, (gpointer) window);
3349 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3353 if (result_len + old_length > 1000) {
3354 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3355 dgettext("hildon-common-strings",
3356 "ckdg_ib_maximum_characters_reached"));
3359 g_string_free (result, TRUE);
3363 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3366 ModestMsgEditWindowPrivate *priv = NULL;
3368 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3369 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3371 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3374 gtk_widget_show_all (priv->find_toolbar);
3375 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3377 gtk_widget_hide_all (priv->find_toolbar);
3378 gtk_widget_grab_focus (priv->msg_body);
3384 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3386 GtkTextIter *match_start,
3387 GtkTextIter *match_end)
3389 GtkTextIter end_iter;
3390 gchar *str_casefold;
3393 gchar *range_casefold;
3396 gboolean result = FALSE;
3403 gtk_text_iter_forward_to_end (&end_iter);
3405 str_casefold = g_utf8_casefold (str, -1);
3406 str_chars_n = strlen (str);
3408 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3409 range_casefold = g_utf8_casefold (range_text, -1);
3410 range_chars_n = strlen (range_casefold);
3412 if (range_chars_n < str_chars_n) {
3413 g_free (str_casefold);
3414 g_free (range_text);
3415 g_free (range_casefold);
3419 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3420 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3421 if (!g_utf8_collate (range_subtext, str_casefold)) {
3422 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3424 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3425 match_start, match_end, NULL);
3426 g_free (found_text);
3428 g_free (range_subtext);
3432 g_free (str_casefold);
3433 g_free (range_text);
3434 g_free (range_casefold);
3441 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3442 ModestMsgEditWindow *window)
3444 gchar *current_search = NULL;
3445 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3447 GtkTextIter selection_start, selection_end;
3448 GtkTextIter match_start, match_end;
3449 gboolean continue_search = FALSE;
3451 if (message_is_empty (window)) {
3452 g_free (priv->last_search);
3453 priv->last_search = NULL;
3454 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3458 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3459 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3460 g_free (current_search);
3461 g_free (priv->last_search);
3462 priv->last_search = NULL;
3463 /* Information banner about empty search */
3464 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3468 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3469 continue_search = TRUE;
3471 g_free (priv->last_search);
3472 priv->last_search = g_strdup (current_search);
3475 if (continue_search) {
3476 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3477 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3478 &match_start, &match_end);
3480 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3482 GtkTextIter buffer_start;
3483 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3484 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3485 &match_start, &match_end);
3487 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3490 /* Mark as selected the string found in search */
3492 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3493 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3494 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3496 g_free (priv->last_search);
3497 priv->last_search = NULL;
3499 g_free (current_search);
3503 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3504 ModestMsgEditWindow *window)
3506 GtkToggleAction *toggle;
3507 ModestWindowPrivate *parent_priv;
3508 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3510 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3511 gtk_toggle_action_set_active (toggle, FALSE);
3515 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3517 ModestMsgEditWindowPrivate *priv;
3519 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3524 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3527 ModestMsgEditWindowPrivate *priv;
3529 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3535 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3538 ModestMsgEditWindowPrivate *priv;
3539 TnyHeader *header = NULL;
3541 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3542 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3544 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3545 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3547 if (priv->draft_msg != NULL) {
3548 g_object_unref (priv->draft_msg);
3551 if (draft != NULL) {
3552 g_object_ref (draft);
3553 header = tny_msg_get_header (draft);
3554 if (priv->msg_uid) {
3555 g_free (priv->msg_uid);
3556 priv->msg_uid = NULL;
3558 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3559 if (GTK_WIDGET_REALIZED (window)) {
3560 if (!modest_window_mgr_register_window (mgr, MODEST_WINDOW (window), NULL)) {
3561 gtk_widget_destroy (GTK_WIDGET (window));
3567 priv->draft_msg = draft;
3571 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3572 GtkTextIter *start, GtkTextIter *end,
3575 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3576 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3579 if (tag == NULL+13) return;
3580 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3581 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3582 replace_with_images (window, priv->images);
3587 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3590 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3592 g_return_if_fail (TNY_IS_MIME_PART (part));
3593 tny_list_prepend (priv->attachments, (GObject *) part);
3594 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3595 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3596 gtk_widget_show_all (priv->attachments_caption);
3597 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3601 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3603 ModestMsgEditWindowPrivate *priv;
3605 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3606 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3608 return priv->msg_uid;
3612 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3613 ModestMsgEditWindowWidgetType widget_type)
3615 ModestMsgEditWindowPrivate *priv;
3617 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3618 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3620 switch (widget_type) {
3621 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3622 return priv->msg_body;
3624 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3625 return priv->to_field;
3627 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3628 return priv->cc_field;
3630 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3631 return priv->bcc_field;
3633 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3634 return priv->subject_field;
3636 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3637 return priv->attachments_view;
3645 remove_tags (WPTextBuffer *buffer)
3647 GtkTextIter start, end;
3649 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3650 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3652 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3656 on_account_removed (TnyAccountStore *account_store,
3657 TnyAccount *account,
3660 /* Do nothing if it's a store account, because we use the
3661 transport to send the messages */
3662 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3663 const gchar *parent_acc = NULL;
3664 const gchar *our_acc = NULL;
3666 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3667 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3668 /* Close this window if I'm showing a message of the removed account */
3669 if (strcmp (parent_acc, our_acc) == 0)
3670 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3675 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3677 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3679 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3685 set_zoom_do_nothing (ModestWindow *window,
3691 get_zoom_do_nothing (ModestWindow *window)