1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
42 #include <modest-account-mgr.h>
43 #include <modest-account-mgr-helpers.h>
45 #include <widgets/modest-msg-edit-window.h>
46 #include <modest-selector-picker.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <wptextview.h>
65 #include <wptextbuffer.h>
66 #include "modest-scroll-area.h"
67 #include "modest-msg-edit-window-ui-dimming.h"
69 #include "modest-hildon-includes.h"
70 #ifdef MODEST_HAVE_HILDON0_WIDGETS
71 #include <hildon-widgets/hildon-color-chooser.h>
73 #include "widgets/modest-msg-edit-window-ui.h"
74 #ifdef MODEST_HAVE_HILDON0_WIDGETS
75 #include <libgnomevfs/gnome-vfs-mime-utils.h>
77 #include <libgnomevfs/gnome-vfs-mime.h>
79 #include <modest-utils.h>
80 #include "modest-maemo-utils.h"
83 #define DEFAULT_FONT_SIZE 3
84 #define DEFAULT_FONT 2
85 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
86 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
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;
741 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
742 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
744 parent_priv->ui_manager = gtk_ui_manager_new();
745 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
746 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
748 /* Add common actions */
749 gtk_action_group_add_actions (action_group,
750 modest_msg_edit_action_entries,
751 G_N_ELEMENTS (modest_msg_edit_action_entries),
753 gtk_action_group_add_toggle_actions (action_group,
754 modest_msg_edit_toggle_action_entries,
755 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
757 gtk_action_group_add_radio_actions (action_group,
758 modest_msg_edit_alignment_radio_action_entries,
759 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
761 G_CALLBACK (modest_ui_actions_on_change_justify),
763 gtk_action_group_add_radio_actions (action_group,
764 modest_msg_edit_priority_action_entries,
765 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
767 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
769 gtk_action_group_add_radio_actions (action_group,
770 modest_msg_edit_file_format_action_entries,
771 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
772 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
773 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
775 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
776 g_object_unref (action_group);
778 /* Load the UI definition */
779 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
782 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
783 g_clear_error (&error);
786 /* Add accelerators */
787 gtk_window_add_accel_group (GTK_WINDOW (obj),
788 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
790 parent_priv->menubar = NULL;
792 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
794 /* Note: This ModestPairList* must exist for as long as the combo
795 * that uses it, because the ModestComboBox uses the ID opaquely,
796 * so it can't know how to manage its memory. */
797 priv->from_field = modest_selector_picker_new (NULL, g_str_equal);
799 priv->to_field = modest_recpt_editor_new ();
800 priv->cc_field = modest_recpt_editor_new ();
801 priv->bcc_field = modest_recpt_editor_new ();
802 subject_box = gtk_hbox_new (FALSE, 0);
803 priv->priority_icon = gtk_image_new ();
804 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
805 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
806 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
807 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
808 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
809 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
810 priv->add_attachment_button = gtk_button_new ();
811 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
812 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
813 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
814 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
815 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
816 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
817 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
818 priv->attachments_view = modest_attachments_view_new (NULL);
820 priv->header_box = gtk_vbox_new (FALSE, 0);
822 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
823 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
824 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
825 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
826 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
827 g_object_unref (size_group);
829 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
830 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
831 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
832 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
833 gtk_size_group_add_widget (size_group, priv->subject_field);
834 gtk_size_group_add_widget (size_group, priv->attachments_view);
835 g_object_unref (size_group);
837 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
838 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
839 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
840 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
841 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
842 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
843 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
846 priv->msg_body = wp_text_view_new ();
847 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
848 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
849 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
850 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
851 #if (GTK_MINOR_VERSION >= 10)
852 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
853 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
855 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
856 deserialize_type, TRUE);
858 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
860 priv->find_toolbar = hildon_find_toolbar_new (NULL);
861 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
863 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
865 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
866 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
867 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
868 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
870 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
872 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
873 priv->frame = gtk_frame_new (NULL);
874 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
876 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
877 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
878 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
880 window_box = gtk_vbox_new (FALSE, 0);
881 gtk_container_add (GTK_CONTAINER(obj), window_box);
883 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
885 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
887 /* Set window icon */
888 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
890 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
891 g_object_unref (window_icon);
896 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
898 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
900 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
901 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
902 priv->clipboard_change_handler_id))
903 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
904 priv->clipboard_change_handler_id);
905 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
906 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
907 priv->default_clipboard_change_handler_id))
908 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
909 priv->default_clipboard_change_handler_id);
911 if (priv->account_removed_handler_id &&
912 g_signal_handler_is_connected (modest_runtime_get_account_store (),
913 priv->account_removed_handler_id))
914 g_signal_handler_disconnect(modest_runtime_get_account_store (),
915 priv->account_removed_handler_id);
919 modest_msg_edit_window_finalize (GObject *obj)
921 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
923 /* Sanity check: shouldn't be needed, the window mgr should
924 call this function before */
925 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
927 if (priv->font_dialog != NULL) {
928 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
931 if (priv->clipboard_text != NULL) {
932 g_free (priv->clipboard_text);
933 priv->clipboard_text = NULL;
936 if (priv->draft_msg != NULL) {
937 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
938 if (TNY_IS_HEADER (header)) {
939 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
940 modest_window_mgr_unregister_header (mgr, header);
942 g_object_unref (priv->draft_msg);
943 priv->draft_msg = NULL;
945 if (priv->outbox_msg != NULL) {
946 TnyHeader *header = tny_msg_get_header (priv->outbox_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->outbox_msg);
952 priv->outbox_msg = NULL;
954 if (priv->scroll_drag_timeout_id > 0) {
955 g_source_remove (priv->scroll_drag_timeout_id);
956 priv->scroll_drag_timeout_id = 0;
958 if (priv->clipboard_owner_idle > 0) {
959 g_source_remove (priv->clipboard_owner_idle);
960 priv->clipboard_owner_idle = 0;
962 if (priv->original_account_name)
963 g_free (priv->original_account_name);
964 g_free (priv->msg_uid);
965 g_free (priv->last_search);
966 g_slist_free (priv->font_items_group);
967 g_slist_free (priv->size_items_group);
968 g_object_unref (priv->attachments);
969 g_object_unref (priv->images);
971 /* This had to stay alive for as long as the combobox that used it: */
972 modest_pair_list_free (priv->from_field_protos);
974 G_OBJECT_CLASS(parent_class)->finalize (obj);
978 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
980 GdkPixbufLoader *loader;
986 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
988 if (loader == NULL) {
994 tny_stream_reset (TNY_STREAM (stream));
995 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
996 GError *error = NULL;
997 unsigned char read_buffer[128];
999 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1001 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1006 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1008 g_object_ref (pixbuf);
1009 gdk_pixbuf_loader_close (loader, NULL);
1010 g_object_unref (loader);
1015 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1016 GdkPixbuf *new_pixbuf;
1018 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1019 gdk_pixbuf_get_width (pixbuf);
1020 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1021 g_object_unref (pixbuf);
1022 pixbuf = new_pixbuf;
1026 *stream_size = size;
1032 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1034 ModestMsgEditWindowPrivate *priv;
1037 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1039 for (iter = tny_list_create_iterator (attachments);
1040 !tny_iterator_is_done (iter);
1041 tny_iterator_next (iter)) {
1042 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1043 const gchar *cid = tny_mime_part_get_content_id (part);
1044 const gchar *mime_type = tny_mime_part_get_content_type (part);
1045 if ((cid != NULL)&&(mime_type != NULL)) {
1046 guint64 stream_size;
1047 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1048 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1051 g_object_unref (stream);
1053 if (pixbuf != NULL) {
1054 priv->images_count ++;
1055 priv->images_size += stream_size;
1056 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1057 g_object_unref (pixbuf);
1060 g_object_unref (part);
1062 g_object_unref (iter);
1066 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1068 TnyMimePart *parent = NULL;
1069 const gchar *content_type = NULL;
1070 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1072 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1074 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1075 parent = g_object_ref (msg);
1076 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1077 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1080 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1081 iter = tny_list_create_iterator (parts);
1082 while (!tny_iterator_is_done (iter)) {
1084 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1085 content_type = tny_mime_part_get_content_type (part);
1086 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1090 g_object_unref (part);
1092 tny_iterator_next (iter);
1094 g_object_unref (iter);
1095 g_object_unref (parts);
1098 if (parent != NULL) {
1099 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1102 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1103 iter = tny_list_create_iterator (parts);
1104 while (!tny_iterator_is_done (iter)) {
1106 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1107 content_type = tny_mime_part_get_content_type (part);
1108 if (content_type && g_str_has_prefix (content_type, "image/")) {
1109 tny_list_prepend (priv->images, (GObject *) part);
1111 g_object_unref (part);
1112 tny_iterator_next (iter);
1114 g_object_unref (iter);
1115 g_object_unref (parts);
1116 g_object_unref (parent);
1121 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1124 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1126 for (iter = tny_list_create_iterator (attachments) ;
1127 !tny_iterator_is_done (iter);
1128 tny_iterator_next (iter)) {
1129 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1130 const gchar *cid = tny_mime_part_get_content_id (part);
1132 char *invalid = NULL;
1133 gint int_cid = strtol (cid, &invalid, 10);
1134 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1135 priv->next_cid = int_cid + 1;
1138 g_object_unref (part);
1140 g_object_unref (iter);
1144 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1147 gchar *to, *cc, *bcc, *subject;
1149 ModestMsgEditWindowPrivate *priv;
1151 TnyHeaderFlags priority_flags;
1152 TnyFolder *msg_folder;
1153 gboolean is_html = FALSE;
1155 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1156 g_return_if_fail (TNY_IS_MSG (msg));
1158 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1160 header = tny_msg_get_header (msg);
1161 to = tny_header_dup_to (header);
1162 cc = tny_header_dup_cc (header);
1163 bcc = tny_header_dup_bcc (header);
1164 subject = tny_header_dup_subject (header);
1165 priority_flags = tny_header_get_priority (header);
1168 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1170 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1171 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1172 gtk_widget_show (priv->cc_caption);
1173 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1174 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1175 gtk_widget_hide (priv->cc_caption);
1178 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1179 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1180 gtk_widget_show (priv->bcc_caption);
1181 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1182 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1183 gtk_widget_hide (priv->bcc_caption);
1186 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1187 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1190 update_window_title (self);
1192 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1193 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1195 if ((body == NULL)||(body[0] == '\0')) {
1197 body = modest_text_utils_convert_to_html ("");
1200 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1201 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1204 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1207 /* Add attachments to the view */
1208 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1209 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1210 if (tny_list_get_length (priv->attachments) == 0) {
1211 gtk_widget_hide (priv->attachments_caption);
1213 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1214 gtk_widget_show_all (priv->attachments_caption);
1216 get_related_images (self, msg);
1217 update_next_cid (self, priv->attachments);
1218 update_next_cid (self, priv->images);
1219 replace_with_images (self, priv->images);
1221 if (preserve_is_rich && !is_html) {
1222 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1223 /* Get the default format required from configuration */
1224 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1225 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1228 /* Set the default focus depending on having already a To: field or not */
1229 if ((!to)||(*to == '\0')) {
1230 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1232 gtk_widget_grab_focus (priv->msg_body);
1235 /* TODO: lower priority, select in the From: combo to the
1236 value that comes from msg <- not sure, should it be
1239 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1241 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1242 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1244 modest_msg_edit_window_set_modified (self, FALSE);
1246 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1247 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1248 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1249 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1251 if (priv->msg_uid) {
1252 g_free (priv->msg_uid);
1253 priv->msg_uid = NULL;
1256 /* we should set a reference to the incoming message if it is a draft */
1257 msg_folder = tny_msg_get_folder (msg);
1259 if (modest_tny_folder_is_local_folder (msg_folder)) {
1260 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1261 if (type == TNY_FOLDER_TYPE_INVALID)
1262 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1264 if (type == TNY_FOLDER_TYPE_DRAFTS)
1265 priv->draft_msg = g_object_ref(msg);
1266 if (type == TNY_FOLDER_TYPE_OUTBOX)
1267 priv->outbox_msg = g_object_ref(msg);
1268 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1270 g_object_unref (msg_folder);
1280 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1283 GList *item_children, *node;
1284 GtkWidget *bin_child;
1286 bin_child = gtk_bin_get_child (GTK_BIN(item));
1288 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1290 for (node = item_children; node != NULL; node = g_list_next (node)) {
1291 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1292 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1295 g_list_free (item_children);
1299 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1302 GList *item_children, *node;
1304 box = gtk_bin_get_child (GTK_BIN (item));
1305 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1306 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1308 for (node = item_children; node != NULL; node = g_list_next (node)) {
1309 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1310 if (GTK_IS_TOGGLE_BUTTON (node->data))
1311 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1312 else if (GTK_IS_BUTTON (node->data))
1313 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1315 g_list_free (item_children);
1320 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1322 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1323 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1324 GtkWidget *placeholder;
1325 GtkWidget *tool_item;
1330 GtkWidget *sizes_menu;
1331 GtkWidget *fonts_menu;
1332 GSList *radio_group = NULL;
1333 GSList *node = NULL;
1337 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1338 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1340 /* Font color placeholder */
1341 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1342 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1345 tool_item = GTK_WIDGET (gtk_tool_item_new ());
1346 priv->font_color_button = hildon_color_button_new ();
1347 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1348 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1349 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
1350 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1351 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1352 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1353 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1355 G_CALLBACK (modest_msg_edit_window_color_button_change),
1358 /* Font size and face placeholder */
1359 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1360 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1362 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1363 priv->size_tool_button_label = gtk_label_new (NULL);
1364 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1365 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1366 size_text,"</span>", NULL);
1367 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1369 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1370 sizes_menu = gtk_menu_new ();
1371 priv->size_items_group = NULL;
1373 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1374 GtkWidget *size_menu_item;
1376 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1377 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1378 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1379 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1380 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1381 gtk_widget_show (size_menu_item);
1383 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1387 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1388 GtkWidget *item = (GtkWidget *) node->data;
1389 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1393 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1394 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1395 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1396 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1397 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1398 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1399 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1400 priv->font_size_toolitem = tool_item;
1403 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1404 priv->font_tool_button_label = gtk_label_new (NULL);
1405 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1406 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1408 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1409 fonts_menu = gtk_menu_new ();
1410 priv->font_items_group = NULL;
1412 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1413 GtkWidget *font_menu_item;
1414 GtkWidget *child_label;
1416 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1417 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1418 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1419 wp_get_font_name (font_index), "</span>", NULL);
1420 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1423 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1424 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1425 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1426 gtk_widget_show (font_menu_item);
1428 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1431 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1432 GtkWidget *item = (GtkWidget *) node->data;
1433 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1436 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1437 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1438 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1439 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1440 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1441 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1442 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1443 priv->font_face_toolitem = tool_item;
1445 /* Set expand and homogeneous for remaining items */
1446 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
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 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1450 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1451 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1452 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1453 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1454 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1456 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1457 will not show the tool items added to the placeholders) */
1458 gtk_widget_show_all (parent_priv->toolbar);
1460 /* Set the no show all *after* showing all items. We do not
1461 want the toolbar to be shown with a show all because it
1462 could go agains the gconf setting regarding showing or not
1463 the toolbar of the editor window */
1464 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1470 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1473 ModestWindowPrivate *parent_priv;
1474 ModestMsgEditWindowPrivate *priv;
1475 ModestDimmingRulesGroup *menu_rules_group = NULL;
1476 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1477 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1478 ModestWindowMgr *mgr = NULL;
1480 g_return_val_if_fail (msg, NULL);
1481 g_return_val_if_fail (account_name, NULL);
1483 mgr = modest_runtime_get_window_mgr ();
1485 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1487 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1488 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1490 /* Menubar. Update the state of some toggles */
1491 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1492 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1493 priv->from_field_protos = get_transports ();
1494 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1495 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1496 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1498 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1499 hildon_touch_selector_get_current_text
1500 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1501 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1502 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1505 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1507 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1509 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1511 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1513 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1514 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1515 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1516 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1517 /* Add common dimming rules */
1518 modest_dimming_rules_group_add_rules (menu_rules_group,
1519 modest_msg_edit_window_menu_dimming_entries,
1520 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1521 MODEST_WINDOW (obj));
1522 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1523 modest_msg_edit_window_toolbar_dimming_entries,
1524 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1525 MODEST_WINDOW (obj));
1526 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1527 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1528 MODEST_WINDOW (obj));
1529 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1530 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1531 MODEST_WINDOW (obj));
1532 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1533 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1534 MODEST_WINDOW (obj));
1535 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1536 modest_msg_edit_window_clipboard_dimming_entries,
1537 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1538 MODEST_WINDOW (obj));
1539 /* Insert dimming rules group for this window */
1540 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1541 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1542 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1543 /* Checks the dimming rules */
1544 g_object_unref (menu_rules_group);
1545 g_object_unref (toolbar_rules_group);
1546 g_object_unref (clipboard_rules_group);
1547 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1549 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1551 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1552 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1553 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1554 priv->update_caption_visibility = TRUE;
1556 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1558 /* Track account-removed signal, this window should be closed
1559 in the case we're creating a mail associated to the account
1561 priv->account_removed_handler_id =
1562 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1564 G_CALLBACK(on_account_removed),
1567 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1569 return (ModestWindow*) obj;
1573 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1575 GString **string_buffer = (GString **) user_data;
1577 *string_buffer = g_string_append (*string_buffer, buffer);
1583 * @result: A new string which should be freed with g_free().
1586 get_formatted_data (ModestMsgEditWindow *edit_window)
1588 ModestMsgEditWindowPrivate *priv;
1589 GString *string_buffer = g_string_new ("");
1591 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1593 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1595 modest_text_utils_hyperlinkify (string_buffer);
1597 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1599 return g_string_free (string_buffer, FALSE);
1604 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1607 const gchar *account_name;
1608 ModestMsgEditWindowPrivate *priv;
1609 TnyIterator *att_iter;
1611 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1613 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1615 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1616 g_return_val_if_fail (account_name, NULL);
1619 /* don't free these (except from) */
1620 data = g_slice_new0 (MsgData);
1621 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1623 data->account_name = g_strdup (account_name);
1624 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1625 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1626 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1627 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1628 if (priv->draft_msg) {
1629 data->draft_msg = g_object_ref (priv->draft_msg);
1630 } else if (priv->outbox_msg) {
1631 data->draft_msg = g_object_ref (priv->outbox_msg);
1633 data->draft_msg = NULL;
1636 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1638 gtk_text_buffer_get_bounds (buf, &b, &e);
1639 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1641 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1642 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1644 data->html_body = NULL;
1646 /* deep-copy the data */
1647 att_iter = tny_list_create_iterator (priv->attachments);
1648 data->attachments = NULL;
1649 while (!tny_iterator_is_done (att_iter)) {
1650 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1651 if (!(TNY_IS_MIME_PART(part))) {
1652 g_warning ("strange data in attachment list");
1653 g_object_unref (part);
1654 tny_iterator_next (att_iter);
1657 data->attachments = g_list_append (data->attachments,
1659 tny_iterator_next (att_iter);
1661 g_object_unref (att_iter);
1663 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1664 att_iter = tny_list_create_iterator (priv->images);
1665 data->images = NULL;
1666 while (!tny_iterator_is_done (att_iter)) {
1667 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1669 if (!(TNY_IS_MIME_PART(part))) {
1670 g_warning ("strange data in attachment list");
1671 g_object_unref (part);
1672 tny_iterator_next (att_iter);
1675 cid = tny_mime_part_get_content_id (part);
1677 gchar *image_tag_id;
1678 GtkTextTag *image_tag;
1680 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1681 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1682 g_free (image_tag_id);
1684 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1686 ((gtk_text_iter_has_tag (&iter, image_tag))||
1687 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1688 data->images = g_list_append (data->images,
1689 g_object_ref (part));
1691 g_object_unref (part);
1692 tny_iterator_next (att_iter);
1694 g_object_unref (att_iter);
1696 data->priority_flags = priv->priority_flags;
1703 unref_gobject (GObject *obj, gpointer data)
1705 if (!G_IS_OBJECT(obj))
1707 g_object_unref (obj);
1711 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1714 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1722 g_free (data->from);
1723 g_free (data->subject);
1724 g_free (data->plain_body);
1725 g_free (data->html_body);
1726 g_free (data->account_name);
1728 if (data->draft_msg != NULL) {
1729 g_object_unref (data->draft_msg);
1730 data->draft_msg = NULL;
1733 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1734 g_list_free (data->attachments);
1735 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1736 g_list_free (data->images);
1738 g_slice_free (MsgData, data);
1742 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1744 guint64 *parts_size)
1746 ModestMsgEditWindowPrivate *priv;
1748 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1750 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1752 /* TODO: add images */
1753 *parts_size += priv->images_size;
1754 *parts_count += priv->images_count;
1759 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1762 ModestMsgEditWindowPrivate *priv = NULL;
1763 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1765 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1767 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1769 return MODEST_MSG_EDIT_FORMAT_HTML;
1771 return MODEST_MSG_EDIT_FORMAT_TEXT;
1775 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1776 ModestMsgEditFormat format)
1778 ModestMsgEditWindowPrivate *priv;
1780 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1781 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1784 case MODEST_MSG_EDIT_FORMAT_HTML:
1785 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1787 case MODEST_MSG_EDIT_FORMAT_TEXT:
1788 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1791 g_return_if_reached ();
1795 ModestMsgEditFormatState *
1796 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1798 ModestMsgEditFormatState *format_state = NULL;
1799 ModestMsgEditWindowPrivate *priv;
1800 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1802 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1803 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1805 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1807 format_state = g_new0 (ModestMsgEditFormatState, 1);
1808 format_state->bold = buffer_format->bold&0x1;
1809 format_state->italics = buffer_format->italic&0x1;
1810 format_state->bullet = buffer_format->bullet&0x1;
1811 format_state->color = buffer_format->color;
1812 format_state->font_size = buffer_format->font_size;
1813 format_state->font_family = wp_get_font_name (buffer_format->font);
1814 format_state->justification = buffer_format->justification;
1815 g_free (buffer_format);
1817 return format_state;
1822 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1823 const ModestMsgEditFormatState *format_state)
1825 ModestMsgEditWindowPrivate *priv;
1826 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1827 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1828 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1829 g_return_if_fail (format_state != NULL);
1831 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1832 gtk_widget_grab_focus (priv->msg_body);
1833 buffer_format->bold = (format_state->bold != FALSE);
1834 buffer_format->italic = (format_state->italics != FALSE);
1835 buffer_format->color = format_state->color;
1836 buffer_format->font_size = format_state->font_size;
1837 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1838 buffer_format->justification = format_state->justification;
1839 buffer_format->bullet = format_state->bullet;
1841 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1843 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1844 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1845 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1846 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1847 buffer_format->cs.font = (buffer_format->font != current_format->font);
1848 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1849 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1851 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1852 if (buffer_format->cs.bold) {
1853 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1854 GINT_TO_POINTER (buffer_format->bold&0x1));
1856 if (buffer_format->cs.italic) {
1857 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1858 GINT_TO_POINTER (buffer_format->italic&0x1));
1860 if (buffer_format->cs.color) {
1861 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1862 GINT_TO_POINTER (&(buffer_format->color)));
1864 if (buffer_format->cs.font_size) {
1865 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1866 GINT_TO_POINTER (buffer_format->font_size));
1868 if (buffer_format->cs.justification) {
1869 switch (buffer_format->justification) {
1870 case GTK_JUSTIFY_LEFT:
1871 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1872 GINT_TO_POINTER(TRUE));
1874 case GTK_JUSTIFY_CENTER:
1875 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1876 GINT_TO_POINTER(TRUE));
1878 case GTK_JUSTIFY_RIGHT:
1879 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1880 GINT_TO_POINTER(TRUE));
1887 if (buffer_format->cs.font) {
1888 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1889 GINT_TO_POINTER (buffer_format->font));
1891 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1892 if (buffer_format->cs.bullet) {
1893 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1894 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1896 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1898 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1900 g_free (current_format);
1902 /* Check dimming rules */
1903 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1904 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1908 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1910 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1912 ModestWindowPrivate *parent_priv;
1913 ModestMsgEditWindowPrivate *priv;
1914 GtkWidget *new_size_menuitem;
1915 GtkWidget *new_font_menuitem;
1917 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1918 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1920 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1921 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1922 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1923 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1925 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1926 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1927 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1930 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1932 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1933 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1935 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1936 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1938 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1939 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1942 switch (buffer_format->justification)
1944 case GTK_JUSTIFY_LEFT:
1945 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1947 case GTK_JUSTIFY_CENTER:
1948 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1950 case GTK_JUSTIFY_RIGHT:
1951 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1958 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1960 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1961 G_CALLBACK (modest_msg_edit_window_color_button_change),
1963 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1964 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1965 G_CALLBACK (modest_msg_edit_window_color_button_change),
1968 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1969 buffer_format->font_size))->data);
1970 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1974 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1975 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1976 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1978 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1979 G_CALLBACK (modest_msg_edit_window_size_change),
1981 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1982 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1983 G_CALLBACK (modest_msg_edit_window_size_change),
1987 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1988 buffer_format->font))->data);
1989 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1993 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1994 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1995 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1997 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1998 G_CALLBACK (modest_msg_edit_window_font_change),
2000 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2001 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2002 G_CALLBACK (modest_msg_edit_window_font_change),
2006 g_free (buffer_format);
2010 #ifdef MODEST_HILDON_VERSION_0
2012 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2015 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2016 ModestMsgEditWindowPrivate *priv;
2017 GtkWidget *dialog = NULL;
2019 GdkColor *new_color = NULL;
2021 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2022 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2024 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2025 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2026 g_free (buffer_format);
2028 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2029 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2030 if (new_color != NULL) {
2031 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2032 (gpointer) new_color);
2035 gtk_widget_destroy (dialog);
2040 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2043 ModestMsgEditWindowPrivate *priv;
2044 GtkWidget *dialog = NULL;
2046 GdkColor *old_color = NULL;
2047 const GdkColor *new_color = NULL;
2049 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2050 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2052 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2053 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2055 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2056 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2057 if (new_color != NULL)
2058 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2060 gtk_widget_destroy (dialog);
2066 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2069 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2070 ModestMsgEditWindowPrivate *priv;
2071 GtkWidget *dialog = NULL;
2073 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2074 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2076 dialog = hildon_color_chooser_new ();
2077 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2078 g_free (buffer_format);
2080 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2082 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2083 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2086 gtk_widget_destroy (dialog);
2091 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2094 ModestMsgEditWindowPrivate *priv;
2095 GtkWidget *dialog = NULL;
2096 GdkColor *old_color = NULL;
2098 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2099 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2101 dialog = hildon_color_chooser_new ();
2102 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2104 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2106 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2107 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2109 gtk_widget_destroy (dialog);
2112 #endif /*!MODEST_HILDON_VERSION_0*/
2117 create_stream_for_uri (const gchar* uri)
2122 TnyStream *result = NULL;
2124 GnomeVFSHandle *handle = NULL;
2125 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2126 if (test == GNOME_VFS_OK) {
2127 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2128 /* Streams over OBEX (Bluetooth) are not seekable but
2129 * we expect them to be (we might need to read them
2130 * several times). So if this is a Bluetooth URI just
2131 * read the whole file into memory (this is not a fast
2132 * protocol so we can assume that these files are not
2133 * going to be very big) */
2134 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2135 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2136 TnyStream *memstream = tny_camel_mem_stream_new ();
2137 tny_stream_write_to_stream (vfssstream, memstream);
2138 g_object_unref (vfssstream);
2141 result = vfssstream;
2149 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2152 ModestMsgEditWindowPrivate *priv;
2153 GtkWidget *dialog = NULL;
2155 GSList *uris = NULL;
2156 GSList *uri_node = NULL;
2158 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2160 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2161 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2162 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2164 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2166 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2167 GTK_WINDOW (dialog));
2169 response = gtk_dialog_run (GTK_DIALOG (dialog));
2171 case GTK_RESPONSE_OK:
2172 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2177 gtk_widget_destroy (dialog);
2179 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2181 GnomeVFSHandle *handle = NULL;
2182 GnomeVFSResult result;
2183 GtkTextIter position;
2184 GtkTextMark *insert_mark;
2186 uri = (const gchar *) uri_node->data;
2187 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2188 if (result == GNOME_VFS_OK) {
2190 GnomeVFSFileInfo *info;
2191 gchar *filename, *basename, *escaped_filename;
2192 TnyMimePart *mime_part;
2194 const gchar *mime_type = NULL;
2195 GnomeVFSURI *vfs_uri;
2196 guint64 stream_size;
2198 gnome_vfs_close (handle);
2199 vfs_uri = gnome_vfs_uri_new (uri);
2201 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2202 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2203 g_free (escaped_filename);
2204 gnome_vfs_uri_unref (vfs_uri);
2205 info = gnome_vfs_file_info_new ();
2207 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2208 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2210 mime_type = gnome_vfs_file_info_get_mime_type (info);
2212 mime_part = tny_platform_factory_new_mime_part
2213 (modest_runtime_get_platform_factory ());
2215 TnyStream *stream = create_stream_for_uri (uri);
2217 if (stream == NULL) {
2219 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2221 g_object_unref (mime_part);
2222 gnome_vfs_file_info_unref (info);
2226 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2228 content_id = g_strdup_printf ("%d", priv->next_cid);
2229 tny_mime_part_set_content_id (mime_part, content_id);
2230 g_free (content_id);
2233 basename = g_path_get_basename (filename);
2234 tny_mime_part_set_filename (mime_part, basename);
2237 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2239 if (pixbuf != NULL) {
2240 priv->images_size += stream_size;
2241 priv->images_count ++;
2242 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2243 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2244 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2247 tny_list_prepend (priv->images, (GObject *) mime_part);
2248 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2250 g_object_unref (mime_part);
2251 gnome_vfs_file_info_unref (info);
2260 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2262 GtkWidget *dialog = NULL;
2264 GSList *uris = NULL;
2266 GnomeVFSFileSize total_size, allowed_size;
2267 ModestMsgEditWindowPrivate *priv;
2271 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2273 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2275 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2278 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2279 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2280 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2281 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
2283 response = gtk_dialog_run (GTK_DIALOG (dialog));
2285 case GTK_RESPONSE_OK:
2286 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2291 gtk_widget_destroy (dialog);
2293 /* allowed size is the maximum size - what's already there */
2294 modest_attachments_view_get_sizes (
2295 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2296 &att_num, &att_size);
2297 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2300 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2302 const gchar *uri = (const gchar *) uri_node->data;
2304 total_size += modest_msg_edit_window_attach_file_one
2305 (window, uri, allowed_size);
2307 if (total_size > allowed_size) {
2308 g_warning ("%s: total size: %u",
2309 __FUNCTION__, (unsigned int)total_size);
2313 allowed_size -= total_size;
2317 g_slist_foreach (uris, (GFunc) g_free, NULL);
2318 g_slist_free (uris);
2323 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2325 GnomeVFSFileSize allowed_size)
2328 GnomeVFSHandle *handle = NULL;
2329 ModestMsgEditWindowPrivate *priv;
2330 GnomeVFSResult result;
2331 GnomeVFSFileSize size = 0;
2332 g_return_val_if_fail (window, 0);
2333 g_return_val_if_fail (uri, 0);
2335 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2337 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2338 if (result == GNOME_VFS_OK) {
2339 TnyMimePart *mime_part;
2341 const gchar *mime_type = NULL;
2343 gchar *escaped_filename;
2346 GnomeVFSFileInfo *info;
2347 GnomeVFSURI *vfs_uri;
2349 gnome_vfs_close (handle);
2350 vfs_uri = gnome_vfs_uri_new (uri);
2353 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2354 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2355 g_free (escaped_filename);
2356 gnome_vfs_uri_unref (vfs_uri);
2358 info = gnome_vfs_file_info_new ();
2360 if (gnome_vfs_get_file_info (uri,
2362 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2364 mime_type = gnome_vfs_file_info_get_mime_type (info);
2365 mime_part = tny_platform_factory_new_mime_part
2366 (modest_runtime_get_platform_factory ());
2368 /* try to get the attachment's size; this may fail for weird
2369 * file systems, like obex, upnp... */
2370 if (allowed_size != 0 &&
2371 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2373 if (size > allowed_size) {
2374 modest_platform_information_banner (NULL, NULL,
2375 dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2379 g_warning ("%s: could not get attachment size", __FUNCTION__);
2381 stream = create_stream_for_uri (uri);
2383 if (stream == NULL) {
2385 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2387 g_object_unref (mime_part);
2388 gnome_vfs_file_info_unref (info);
2392 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2393 g_object_unref (stream);
2395 content_id = g_strdup_printf ("%d", priv->next_cid);
2396 tny_mime_part_set_content_id (mime_part, content_id);
2397 g_free (content_id);
2400 basename = g_path_get_basename (filename);
2401 tny_mime_part_set_filename (mime_part, basename);
2404 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2405 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2407 info->size == 0, info->size);
2408 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2409 gtk_widget_show_all (priv->attachments_caption);
2410 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2412 g_object_unref (mime_part);
2413 gnome_vfs_file_info_unref (info);
2420 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2423 ModestMsgEditWindowPrivate *priv;
2426 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2427 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2429 if (att_list == NULL) {
2430 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2432 g_object_ref (att_list);
2435 if (tny_list_get_length (att_list) == 0) {
2436 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2438 gboolean dialog_response;
2439 gchar *message = NULL;
2440 gchar *filename = NULL;
2442 if (tny_list_get_length (att_list) == 1) {
2444 iter = tny_list_create_iterator (att_list);
2445 part = (TnyMimePart *) tny_iterator_get_current (iter);
2446 g_object_unref (iter);
2447 if (TNY_IS_MSG (part)) {
2448 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2450 filename = tny_header_dup_subject (header);
2451 g_object_unref (header);
2453 if (filename == NULL) {
2454 filename = g_strdup (_("mail_va_no_subject"));
2457 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2459 g_object_unref (part);
2461 filename = g_strdup ("");
2463 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2464 tny_list_get_length (att_list)), filename);
2467 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2470 if (dialog_response != GTK_RESPONSE_OK) {
2471 g_object_unref (att_list);
2474 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
2476 for (iter = tny_list_create_iterator (att_list);
2477 !tny_iterator_is_done (iter);
2478 tny_iterator_next (iter)) {
2479 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2480 const gchar *att_id;
2481 tny_list_remove (priv->attachments, (GObject *) mime_part);
2483 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2485 if (tny_list_get_length (priv->attachments) == 0)
2486 gtk_widget_hide (priv->attachments_caption);
2487 att_id = tny_mime_part_get_content_id (mime_part);
2489 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2491 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2492 g_object_unref (mime_part);
2494 g_object_unref (iter);
2497 g_object_unref (att_list);
2499 /* if the last attachment has been removed, focus the Subject: field */
2500 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2501 gtk_widget_grab_focus (priv->subject_field);
2505 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2508 ModestMsgEditWindowPrivate *priv;
2509 GdkColor *new_color;
2510 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2512 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2513 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2516 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2518 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2520 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2522 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2527 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2530 ModestMsgEditWindowPrivate *priv;
2531 gint new_size_index;
2532 ModestMsgEditWindow *window;
2535 window = MODEST_MSG_EDIT_WINDOW (userdata);
2536 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2537 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2539 if (gtk_check_menu_item_get_active (menu_item)) {
2541 WPTextBufferFormat format;
2543 memset (&format, 0, sizeof (format));
2544 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2546 label = gtk_bin_get_child (GTK_BIN (menu_item));
2548 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2549 format.cs.font_size = TRUE;
2550 format.cs.text_position = TRUE;
2551 format.cs.font = TRUE;
2552 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2553 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2555 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2556 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2557 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2559 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2560 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2561 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2567 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2570 ModestMsgEditWindowPrivate *priv;
2571 gint new_font_index;
2572 ModestMsgEditWindow *window;
2575 window = MODEST_MSG_EDIT_WINDOW (userdata);
2576 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2577 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2579 if (gtk_check_menu_item_get_active (menu_item)) {
2582 label = gtk_bin_get_child (GTK_BIN (menu_item));
2584 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2586 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2587 GINT_TO_POINTER(new_font_index)))
2588 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2590 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2591 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2592 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2598 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2600 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2601 ModestWindowPrivate *parent_priv;
2602 ModestWindowMgr *mgr;
2603 gboolean is_fullscreen;
2604 GtkAction *fs_toggle_action;
2607 mgr = modest_runtime_get_window_mgr ();
2608 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2610 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2612 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2613 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2614 if (is_fullscreen != active)
2615 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2623 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2626 ModestMsgEditWindowPrivate *priv = NULL;
2627 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2629 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2630 if (!priv->update_caption_visibility)
2633 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2635 gtk_widget_show (priv->cc_caption);
2637 gtk_widget_hide (priv->cc_caption);
2639 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2643 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2646 ModestMsgEditWindowPrivate *priv = NULL;
2647 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2649 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2650 if (!priv->update_caption_visibility)
2653 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2655 gtk_widget_show (priv->bcc_caption);
2657 gtk_widget_hide (priv->bcc_caption);
2659 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2663 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2664 ModestRecptEditor *editor)
2666 ModestMsgEditWindowPrivate *priv;
2668 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2669 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2671 /* we check for low-mem; in that case, show a warning, and don't allow
2672 * for the addressbook
2674 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2677 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2679 if (editor == NULL) {
2680 GtkWidget *view_focus;
2681 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2683 /* This code should be kept in sync with ModestRecptEditor. The
2684 textview inside the recpt editor is the one that really gets the
2685 focus. As it's inside a scrolled window, and this one inside the
2686 hbox recpt editor inherits from, we'll need to go up in the
2687 hierarchy to know if the text view is part of the recpt editor
2688 or if it's a different text entry */
2690 if (gtk_widget_get_parent (view_focus)) {
2691 GtkWidget *first_parent;
2693 first_parent = gtk_widget_get_parent (view_focus);
2694 if (gtk_widget_get_parent (first_parent) &&
2695 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2696 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2701 editor = MODEST_RECPT_EDITOR (priv->to_field);
2705 modest_address_book_select_addresses (editor);
2710 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2712 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2714 modest_msg_edit_window_open_addressbook (window, NULL);
2718 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2719 gboolean show_toolbar)
2721 ModestWindowPrivate *parent_priv;
2722 const gchar *action_name;
2725 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2726 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2728 /* We can not just use the code of
2729 modest_msg_edit_window_setup_toolbar because it has a
2730 mixture of both initialization and creation code. */
2732 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2734 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2736 /* Update also the actions (to update the toggles in the
2737 menus), we have to do it manually because some other window
2738 of the same time could have changed it (remember that the
2739 toolbar fullscreen mode is shared by all the windows of the
2741 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2742 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2744 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2746 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2747 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2753 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2754 TnyHeaderFlags priority_flags)
2756 ModestMsgEditWindowPrivate *priv;
2757 ModestWindowPrivate *parent_priv;
2759 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2761 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2762 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2764 if (priv->priority_flags != priority_flags) {
2765 GtkAction *priority_action = NULL;
2767 priv->priority_flags = priority_flags;
2769 switch (priority_flags) {
2770 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2771 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2772 gtk_widget_show (priv->priority_icon);
2773 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2774 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2776 case TNY_HEADER_FLAG_LOW_PRIORITY:
2777 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2778 gtk_widget_show (priv->priority_icon);
2779 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2780 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2783 gtk_widget_hide (priv->priority_icon);
2784 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2785 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2788 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2789 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2794 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2797 ModestMsgEditWindowPrivate *priv;
2798 ModestWindowPrivate *parent_priv;
2799 gint current_format;
2801 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2803 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2804 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2806 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2807 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2809 if (current_format != file_format) {
2810 switch (file_format) {
2811 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2812 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2813 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2815 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2819 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2820 response = gtk_dialog_run (GTK_DIALOG (dialog));
2821 gtk_widget_destroy (dialog);
2822 if (response == GTK_RESPONSE_OK) {
2823 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2825 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2826 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2831 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2832 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2833 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2838 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2841 ModestMsgEditWindowPrivate *priv;
2842 WPTextBufferFormat oldfmt, fmt;
2843 gint old_position = 0;
2847 GdkColor *color = NULL;
2848 gboolean bold, bold_set, italic, italic_set;
2849 gboolean underline, underline_set;
2850 gboolean strikethrough, strikethrough_set;
2851 gboolean position_set;
2852 gboolean font_size_set, font_set, color_set;
2855 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2856 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2858 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2859 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2860 GTK_WINDOW(dialog));
2862 /* First we get the currently selected font information */
2863 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2865 switch (oldfmt.text_position) {
2866 case TEXT_POSITION_NORMAL:
2869 case TEXT_POSITION_SUPERSCRIPT:
2877 g_object_set (G_OBJECT (dialog),
2878 "bold", oldfmt.bold != FALSE,
2879 "bold-set", !oldfmt.cs.bold,
2880 "underline", oldfmt.underline != FALSE,
2881 "underline-set", !oldfmt.cs.underline,
2882 "italic", oldfmt.italic != FALSE,
2883 "italic-set", !oldfmt.cs.italic,
2884 "strikethrough", oldfmt.strikethrough != FALSE,
2885 "strikethrough-set", !oldfmt.cs.strikethrough,
2886 "color", &oldfmt.color,
2887 "color-set", !oldfmt.cs.color,
2888 "size", wp_font_size[oldfmt.font_size],
2889 "size-set", !oldfmt.cs.font_size,
2890 "position", old_position,
2891 "position-set", !oldfmt.cs.text_position,
2892 "family", wp_get_font_name (oldfmt.font),
2893 "family-set", !oldfmt.cs.font,
2896 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2897 GTK_WINDOW (dialog));
2898 gtk_widget_show_all (dialog);
2899 priv->font_dialog = dialog;
2900 response = gtk_dialog_run (GTK_DIALOG (dialog));
2901 priv->font_dialog = NULL;
2902 if (response == GTK_RESPONSE_OK) {
2904 g_object_get( dialog,
2906 "bold-set", &bold_set,
2907 "underline", &underline,
2908 "underline-set", &underline_set,
2910 "italic-set", &italic_set,
2911 "strikethrough", &strikethrough,
2912 "strikethrough-set", &strikethrough_set,
2914 "color-set", &color_set,
2916 "size-set", &font_size_set,
2917 "family", &font_name,
2918 "family-set", &font_set,
2919 "position", &position,
2920 "position-set", &position_set,
2925 if (response == GTK_RESPONSE_OK) {
2926 memset(&fmt, 0, sizeof(fmt));
2932 fmt.italic = italic;
2933 fmt.cs.italic = TRUE;
2935 if (underline_set) {
2936 fmt.underline = underline;
2937 fmt.cs.underline = TRUE;
2939 if (strikethrough_set) {
2940 fmt.strikethrough = strikethrough;
2941 fmt.cs.strikethrough = TRUE;
2946 ? TEXT_POSITION_NORMAL
2947 : ( ( position == 1 )
2948 ? TEXT_POSITION_SUPERSCRIPT
2949 : TEXT_POSITION_SUBSCRIPT );
2950 fmt.cs.text_position = TRUE;
2951 fmt.font_size = oldfmt.font_size;
2955 fmt.cs.color = TRUE;
2958 fmt.font = wp_get_font_index(font_name,
2963 if (font_size_set) {
2964 fmt.cs.font_size = TRUE;
2965 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2967 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2968 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2970 gtk_widget_destroy (dialog);
2972 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2976 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2978 ModestMsgEditWindowPrivate *priv;
2980 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2981 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2983 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2985 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2986 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2990 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2992 ModestMsgEditWindowPrivate *priv;
2994 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2995 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2997 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2999 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3000 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3005 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3007 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3009 priv->can_undo = can_undo;
3013 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3015 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3017 priv->can_redo = can_redo;
3021 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3023 ModestMsgEditWindowPrivate *priv;
3024 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3025 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3027 return priv->can_undo;
3031 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3033 ModestMsgEditWindowPrivate *priv;
3034 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3035 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3037 return priv->can_redo;
3042 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3045 GtkTextIter match_start, match_end;
3047 if (image_id == NULL)
3050 gtk_text_buffer_get_start_iter (buffer, &iter);
3052 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3053 GSList *tags = gtk_text_iter_get_tags (&match_start);
3055 for (node = tags; node != NULL; node = g_slist_next (node)) {
3056 GtkTextTag *tag = (GtkTextTag *) node->data;
3057 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3058 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3059 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3061 offset = gtk_text_iter_get_offset (&match_start);
3062 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3063 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3067 gtk_text_iter_forward_char (&iter);
3072 message_is_empty (ModestMsgEditWindow *window)
3074 ModestMsgEditWindowPrivate *priv = NULL;
3076 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3077 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3079 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3080 * so we can ignore markup.
3082 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3085 count = gtk_text_buffer_get_char_count (buf);
3091 msg_body_focus (GtkWidget *focus,
3092 GdkEventFocus *event,
3096 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3097 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3098 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3103 recpt_field_changed (GtkTextBuffer *buffer,
3104 ModestMsgEditWindow *editor)
3106 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3107 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3111 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3113 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3114 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3118 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3121 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3122 GtkTextBuffer *buffer;
3124 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3125 gtk_text_buffer_set_modified (buffer, modified);
3126 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3127 gtk_text_buffer_set_modified (buffer, modified);
3128 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3129 gtk_text_buffer_set_modified (buffer, modified);
3130 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3134 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3136 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3137 const char *account_name;
3138 GtkTextBuffer *buffer;
3140 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3141 if (gtk_text_buffer_get_modified (buffer))
3143 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3144 if (gtk_text_buffer_get_modified (buffer))
3146 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3147 if (gtk_text_buffer_get_modified (buffer))
3149 if (gtk_text_buffer_get_modified (priv->text_buffer))
3151 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3152 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3163 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3165 ModestMsgEditWindowPrivate *priv = NULL;
3167 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3168 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3170 /* check if there's no recipient added */
3171 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3172 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3173 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3174 /* no recipient contents, then select contacts */
3175 modest_msg_edit_window_open_addressbook (window, NULL);
3179 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3180 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3183 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3184 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3187 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3188 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3192 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3193 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3194 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3201 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3202 ModestMsgEditWindow *window)
3204 modest_msg_edit_window_offer_attach_file (window);
3208 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3210 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3212 return priv->clipboard_text;
3216 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3218 ModestMsgEditWindow *window)
3220 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3221 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3223 if (!GTK_WIDGET_VISIBLE (window))
3226 g_object_ref (window);
3227 text = gtk_clipboard_wait_for_text (selection_clipboard);
3229 if (priv->clipboard_text != NULL) {
3230 g_free (priv->clipboard_text);
3232 priv->clipboard_text = text;
3234 if (GTK_WIDGET_VISIBLE (window)) {
3235 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3237 g_object_unref (window);
3240 static gboolean clipboard_owner_change_idle (gpointer userdata)
3242 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3243 ModestMsgEditWindowPrivate *priv;
3245 gdk_threads_enter ();
3246 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3247 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3249 priv->clipboard_owner_idle = 0;
3250 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3251 gdk_threads_leave ();
3257 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3259 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3260 if (priv->clipboard_owner_idle == 0) {
3261 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3266 subject_field_move_cursor (GtkEntry *entry,
3267 GtkMovementStep step,
3272 if (!GTK_WIDGET_VISIBLE (window))
3275 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3279 update_window_title (ModestMsgEditWindow *window)
3281 ModestMsgEditWindowPrivate *priv = NULL;
3282 const gchar *subject;
3284 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3285 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3286 if (subject == NULL || subject[0] == '\0')
3287 subject = _("mail_va_new_email");
3289 gtk_window_set_title (GTK_WINDOW (window), subject);
3294 subject_field_changed (GtkEditable *editable,
3295 ModestMsgEditWindow *window)
3297 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3298 update_window_title (window);
3299 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3300 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3301 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3305 subject_field_insert_text (GtkEditable *editable,
3307 gint new_text_length,
3309 ModestMsgEditWindow *window)
3311 GString *result = g_string_new ("");
3313 gint result_len = 0;
3314 const gchar *entry_text = NULL;
3317 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3318 old_length = g_utf8_strlen (entry_text, -1);
3320 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3321 gunichar c = g_utf8_get_char_validated (current, 8);
3322 /* Invalid unichar, stop */
3328 result = g_string_append_unichar (result, c);
3332 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3333 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3336 /* Prevent endless recursion */
3337 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3338 g_signal_emit_by_name (editable, "insert-text",
3339 (gpointer) result->str, (gpointer) result->len,
3340 (gpointer) position, (gpointer) window);
3341 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3345 if (result_len + old_length > 1000) {
3346 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3347 dgettext("hildon-common-strings",
3348 "ckdg_ib_maximum_characters_reached"));
3351 g_string_free (result, TRUE);
3355 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3358 ModestMsgEditWindowPrivate *priv = NULL;
3360 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3361 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3363 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3366 gtk_widget_show_all (priv->find_toolbar);
3367 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3369 gtk_widget_hide_all (priv->find_toolbar);
3370 gtk_widget_grab_focus (priv->msg_body);
3376 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3378 GtkTextIter *match_start,
3379 GtkTextIter *match_end)
3381 GtkTextIter end_iter;
3382 gchar *str_casefold;
3385 gchar *range_casefold;
3388 gboolean result = FALSE;
3395 gtk_text_iter_forward_to_end (&end_iter);
3397 str_casefold = g_utf8_casefold (str, -1);
3398 str_chars_n = strlen (str);
3400 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3401 range_casefold = g_utf8_casefold (range_text, -1);
3402 range_chars_n = strlen (range_casefold);
3404 if (range_chars_n < str_chars_n) {
3405 g_free (str_casefold);
3406 g_free (range_text);
3407 g_free (range_casefold);
3411 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3412 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3413 if (!g_utf8_collate (range_subtext, str_casefold)) {
3414 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3416 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3417 match_start, match_end, NULL);
3418 g_free (found_text);
3420 g_free (range_subtext);
3424 g_free (str_casefold);
3425 g_free (range_text);
3426 g_free (range_casefold);
3433 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3434 ModestMsgEditWindow *window)
3436 gchar *current_search = NULL;
3437 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3439 GtkTextIter selection_start, selection_end;
3440 GtkTextIter match_start, match_end;
3441 gboolean continue_search = FALSE;
3443 if (message_is_empty (window)) {
3444 g_free (priv->last_search);
3445 priv->last_search = NULL;
3446 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3450 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3451 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3452 g_free (current_search);
3453 g_free (priv->last_search);
3454 priv->last_search = NULL;
3455 /* Information banner about empty search */
3456 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3460 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3461 continue_search = TRUE;
3463 g_free (priv->last_search);
3464 priv->last_search = g_strdup (current_search);
3467 if (continue_search) {
3468 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3469 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3470 &match_start, &match_end);
3472 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3474 GtkTextIter buffer_start;
3475 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3476 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3477 &match_start, &match_end);
3479 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3482 /* Mark as selected the string found in search */
3484 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3485 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3486 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3488 g_free (priv->last_search);
3489 priv->last_search = NULL;
3491 g_free (current_search);
3495 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3496 ModestMsgEditWindow *window)
3498 GtkToggleAction *toggle;
3499 ModestWindowPrivate *parent_priv;
3500 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3502 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3503 gtk_toggle_action_set_active (toggle, FALSE);
3507 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3509 ModestMsgEditWindowPrivate *priv;
3511 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3516 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3519 ModestMsgEditWindowPrivate *priv;
3521 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3527 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3530 ModestMsgEditWindowPrivate *priv;
3531 TnyHeader *header = NULL;
3533 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3534 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3536 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3537 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3539 if (priv->draft_msg != NULL) {
3540 g_object_unref (priv->draft_msg);
3543 if (draft != NULL) {
3544 g_object_ref (draft);
3545 header = tny_msg_get_header (draft);
3546 if (priv->msg_uid) {
3547 g_free (priv->msg_uid);
3548 priv->msg_uid = NULL;
3550 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3551 if (GTK_WIDGET_REALIZED (window))
3552 modest_window_mgr_register_window (mgr, MODEST_WINDOW (window));
3555 priv->draft_msg = draft;
3559 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3560 GtkTextIter *start, GtkTextIter *end,
3563 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3564 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3567 if (tag == NULL+13) return;
3568 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3569 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3570 replace_with_images (window, priv->images);
3575 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3578 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3580 g_return_if_fail (TNY_IS_MIME_PART (part));
3581 tny_list_prepend (priv->attachments, (GObject *) part);
3582 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3583 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3584 gtk_widget_show_all (priv->attachments_caption);
3585 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3589 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3591 ModestMsgEditWindowPrivate *priv;
3593 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3594 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3596 return priv->msg_uid;
3600 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3601 ModestMsgEditWindowWidgetType widget_type)
3603 ModestMsgEditWindowPrivate *priv;
3605 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3606 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3608 switch (widget_type) {
3609 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3610 return priv->msg_body;
3612 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3613 return priv->to_field;
3615 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3616 return priv->cc_field;
3618 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3619 return priv->bcc_field;
3621 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3622 return priv->subject_field;
3624 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3625 return priv->attachments_view;
3633 remove_tags (WPTextBuffer *buffer)
3635 GtkTextIter start, end;
3637 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3638 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3640 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3644 on_account_removed (TnyAccountStore *account_store,
3645 TnyAccount *account,
3648 /* Do nothing if it's a store account, because we use the
3649 transport to send the messages */
3650 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3651 const gchar *parent_acc = NULL;
3652 const gchar *our_acc = NULL;
3654 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3655 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3656 /* Close this window if I'm showing a message of the removed account */
3657 if (strcmp (parent_acc, our_acc) == 0)
3658 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3663 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3665 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3667 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3673 set_zoom_do_nothing (ModestWindow *window,
3679 get_zoom_do_nothing (ModestWindow *window)