1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
42 #include <modest-account-mgr.h>
43 #include <modest-account-mgr-helpers.h>
45 #include <widgets/modest-msg-edit-window.h>
46 #include <modest-selector-picker.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <wptextview.h>
65 #include <wptextbuffer.h>
66 #include "modest-scroll-area.h"
67 #include "modest-msg-edit-window-ui-dimming.h"
69 #include "modest-hildon-includes.h"
70 #ifdef MODEST_HAVE_HILDON0_WIDGETS
71 #include <hildon-widgets/hildon-color-chooser.h>
73 #include "widgets/modest-msg-edit-window-ui.h"
74 #ifdef MODEST_HAVE_HILDON0_WIDGETS
75 #include <libgnomevfs/gnome-vfs-mime-utils.h>
77 #include <libgnomevfs/gnome-vfs-mime.h>
79 #include <modest-utils.h>
80 #include "modest-maemo-utils.h"
81 #include <modest-ui-constants.h>
84 #define DEFAULT_FONT_SIZE 3
85 #define DEFAULT_FONT 2
86 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
87 #define DEFAULT_MAIN_VBOX_SPACING 6
88 #define SUBJECT_MAX_LENGTH 1000
89 #define IMAGE_MAX_WIDTH 560
90 #define DEFAULT_FONT_SCALE 1.5
92 static gboolean is_wp_text_buffer_started = FALSE;
94 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
95 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
96 static void modest_msg_edit_window_finalize (GObject *obj);
98 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
99 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
100 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
102 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
103 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
104 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
105 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
106 GtkTextIter *start, GtkTextIter *end,
108 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
109 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
110 static void subject_field_insert_text (GtkEditable *editable,
112 gint new_text_length,
114 ModestMsgEditWindow *window);
115 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
117 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
119 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
121 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
122 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
123 GdkEventWindowState *event,
125 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
126 ModestRecptEditor *editor);
127 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
128 ModestMsgEditWindow *window);
130 /* ModestWindow methods implementation */
131 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
132 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
133 gboolean show_toolbar);
134 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
136 ModestMsgEditWindow *window);
137 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
138 static void subject_field_move_cursor (GtkEntry *entry,
139 GtkMovementStep step,
143 static void update_window_title (ModestMsgEditWindow *window);
146 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
147 ModestMsgEditWindow *window);
148 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
149 ModestMsgEditWindow *window);
150 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
152 GtkTextIter *match_start,
153 GtkTextIter *match_end);
155 static void remove_tags (WPTextBuffer *buffer);
157 static void on_account_removed (TnyAccountStore *account_store,
161 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
162 static void set_zoom_do_nothing (ModestWindow *window, gdouble zoom);
163 static gdouble get_zoom_do_nothing (ModestWindow *window);
165 static void init_window (ModestMsgEditWindow *obj);
167 gboolean scroll_drag_timeout (gpointer userdata);
168 static void correct_scroll (ModestMsgEditWindow *w);
169 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
170 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
171 ModestMsgEditWindow *userdata);
172 static void text_buffer_mark_set (GtkTextBuffer *buffer,
175 ModestMsgEditWindow *userdata);
176 static void vadj_changed (GtkAdjustment *adj,
177 ModestMsgEditWindow *window);
179 static void DEBUG_BUFFER (WPTextBuffer *buffer)
183 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
185 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
186 while (!gtk_text_iter_is_end (&iter)) {
187 GString *output = g_string_new ("");
188 GSList *toggled_tags;
191 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
192 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
193 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
194 GtkTextTag *tag = (GtkTextTag *) node->data;
196 g_object_get (G_OBJECT (tag), "name", &name, NULL);
197 output = g_string_append (output, name);
198 g_string_append (output, " ");
200 output = g_string_append (output, "] OPENED [ ");
201 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
202 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
203 GtkTextTag *tag = (GtkTextTag *) node->data;
205 g_object_get (G_OBJECT (tag), "name", &name, NULL);
206 output = g_string_append (output, name);
207 g_string_append (output, " ");
209 output = g_string_append (output, "]\n");
210 g_message ("%s", output->str);
211 g_string_free (output, TRUE);
212 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
214 g_message ("END BUFFER");
219 /* static gboolean */
220 /* on_key_pressed (GtkWidget *self, */
221 /* GdkEventKey *event, */
222 /* gpointer user_data); */
224 /* list my signals */
231 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
232 struct _ModestMsgEditWindowPrivate {
235 GtkWidget *header_box;
237 ModestPairList *from_field_protos;
238 GtkWidget *from_field;
239 gchar *original_account_name;
243 GtkWidget *bcc_field;
244 GtkWidget *subject_field;
245 GtkWidget *attachments_view;
246 GtkWidget *priority_icon;
247 GtkWidget *add_attachment_button;
249 GtkWidget *cc_caption;
250 GtkWidget *bcc_caption;
251 gboolean update_caption_visibility;
252 GtkWidget *attachments_caption;
254 GtkTextBuffer *text_buffer;
256 GtkWidget *font_size_toolitem;
257 GtkWidget *font_face_toolitem;
258 GtkWidget *font_color_button;
259 GSList *font_items_group;
260 GtkWidget *font_tool_button_label;
261 GSList *size_items_group;
262 GtkWidget *size_tool_button_label;
264 GtkWidget *find_toolbar;
267 GtkWidget *font_dialog;
270 guint scroll_drag_timeout_id;
274 TnyList *attachments;
279 TnyHeaderFlags priority_flags;
281 gboolean can_undo, can_redo;
282 gulong clipboard_change_handler_id;
283 gulong default_clipboard_change_handler_id;
284 gulong account_removed_handler_id;
285 guint clipboard_owner_idle;
286 gchar *clipboard_text;
295 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
296 MODEST_TYPE_MSG_EDIT_WINDOW, \
297 ModestMsgEditWindowPrivate))
299 static GtkWindowClass *parent_class = NULL;
301 /* uncomment the following if you have defined any signals */
302 /* static guint signals[LAST_SIGNAL] = {0}; */
305 modest_msg_edit_window_get_type (void)
307 static GType my_type = 0;
309 static const GTypeInfo my_info = {
310 sizeof(ModestMsgEditWindowClass),
311 NULL, /* base init */
312 NULL, /* base finalize */
313 (GClassInitFunc) modest_msg_edit_window_class_init,
314 NULL, /* class finalize */
315 NULL, /* class data */
316 sizeof(ModestMsgEditWindow),
318 (GInstanceInitFunc) modest_msg_edit_window_init,
321 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
322 "ModestMsgEditWindow",
330 save_state (ModestWindow *self)
332 modest_widget_memory_save (modest_runtime_get_conf(),
333 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
338 restore_settings (ModestMsgEditWindow *self)
340 ModestConf *conf = NULL;
342 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
344 conf = modest_runtime_get_conf ();
345 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
346 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
347 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
348 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL));
349 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
350 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu");
351 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
352 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
354 /* set initial state of cc and bcc */
355 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
356 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
357 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
358 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
359 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
360 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
362 /* Dim at start clipboard actions */
363 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
364 gtk_action_set_sensitive (action, FALSE);
365 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
366 gtk_action_set_sensitive (action, FALSE);
367 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
368 gtk_action_set_sensitive (action, FALSE);
370 modest_widget_memory_restore (conf,
371 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
376 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
378 GObjectClass *gobject_class;
379 ModestWindowClass *modest_window_class;
380 gobject_class = (GObjectClass*) klass;
381 modest_window_class = (ModestWindowClass*) klass;
383 parent_class = g_type_class_peek_parent (klass);
384 gobject_class->finalize = modest_msg_edit_window_finalize;
386 modest_window_class->set_zoom_func = set_zoom_do_nothing;
387 modest_window_class->get_zoom_func = get_zoom_do_nothing;
388 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
389 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
390 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
391 modest_window_class->save_state_func = save_state;
392 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
394 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
398 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
400 ModestMsgEditWindowPrivate *priv;
401 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
403 priv->msg_body = NULL;
405 priv->from_field = NULL;
406 priv->to_field = NULL;
407 priv->cc_field = NULL;
408 priv->bcc_field = NULL;
409 priv->subject_field = NULL;
410 priv->attachments = TNY_LIST (tny_simple_list_new ());
411 priv->images = TNY_LIST (tny_simple_list_new ());
412 priv->images_size = 0;
413 priv->images_count = 0;
416 priv->cc_caption = NULL;
417 priv->bcc_caption = NULL;
418 priv->update_caption_visibility = FALSE;
420 priv->priority_flags = 0;
422 priv->find_toolbar = NULL;
423 priv->last_search = NULL;
425 priv->draft_msg = NULL;
426 priv->outbox_msg = NULL;
427 priv->msg_uid = NULL;
429 priv->can_undo = FALSE;
430 priv->can_redo = FALSE;
431 priv->clipboard_change_handler_id = 0;
432 priv->default_clipboard_change_handler_id = 0;
433 priv->account_removed_handler_id = 0;
434 priv->clipboard_owner_idle = 0;
435 priv->clipboard_text = NULL;
438 priv->scroll_drag_timeout_id = 0;
439 priv->last_upper = 0.0;
441 priv->font_dialog = NULL;
443 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
444 GTK_WINDOW(obj),"applications_email_editor");
446 if (!is_wp_text_buffer_started) {
447 is_wp_text_buffer_started = TRUE;
448 wp_text_buffer_library_init ();
453 hildon_program_add_window (hildon_program_get_instance(),
458 /* FIXME: this is a dup from the one in gtk/ */
461 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
463 static ModestPairList*
464 get_transports (void)
466 GSList *transports = NULL;
468 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
469 GSList *accounts = modest_account_mgr_account_names (account_mgr,
470 TRUE /* only enabled accounts. */);
472 GSList *cursor = accounts;
474 gchar *account_name = cursor->data;
475 gchar *from_string = NULL;
477 from_string = modest_account_mgr_get_from_string (account_mgr,
481 if (from_string && account_name) {
482 gchar *name = account_name;
483 ModestPair *pair = modest_pair_new ((gpointer) name,
484 (gpointer) from_string , TRUE);
485 transports = g_slist_prepend (transports, pair);
488 cursor = cursor->next;
490 g_slist_free (accounts); /* only free the accounts, not the elements,
491 * because they are used in the pairlist */
495 static void window_focus (GtkWindow *window,
499 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
503 scroll_drag_timeout (gpointer userdata)
505 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
506 ModestMsgEditWindowPrivate *priv;
508 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
510 correct_scroll_without_drag_check (win, TRUE);
512 priv->scroll_drag_timeout_id = 0;
518 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
520 ModestMsgEditWindowPrivate *priv;
523 GdkRectangle rectangle;
529 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
531 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
534 insert = gtk_text_buffer_get_insert (priv->text_buffer);
535 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
537 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
538 vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll));
539 offset = priv->msg_body->allocation.y;
541 new_value = vadj->value;
543 if ((offset + rectangle.y + rectangle.height) >
544 ((gint) (vadj->value +vadj->page_size))) {
545 new_value = (offset + rectangle.y) - vadj->page_size * 0.25;
546 if (new_value > vadj->upper - vadj->page_size)
547 new_value = vadj->upper - vadj->page_size;
548 } else if ((offset + rectangle.y) < ((gint) vadj->value)) {
549 new_value = (offset + rectangle.y - vadj->page_size * 0.75);
550 if (((gint) (new_value + vadj->page_size)) < (offset + rectangle.y + rectangle.height))
551 new_value = offset + rectangle.y + rectangle.height - (gint) vadj->page_size;
554 if (new_value > vadj->value)
555 new_value = vadj->value;
558 if (vadj->value != new_value) {
559 g_signal_emit_by_name (GTK_TEXT_VIEW(priv->msg_body)->layout,
561 vadj->value = new_value;
562 gtk_adjustment_value_changed (vadj);
563 /* invalidate body */
564 window = gtk_widget_get_parent_window (priv->msg_body);
566 gdk_window_invalidate_rect (window, NULL, TRUE);
572 correct_scroll (ModestMsgEditWindow *w)
574 ModestMsgEditWindowPrivate *priv;
576 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
577 if (gtk_grab_get_current () == priv->msg_body) {
578 if (priv->scroll_drag_timeout_id == 0) {
579 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
585 correct_scroll_without_drag_check (w, TRUE);
589 text_buffer_end_user_action (GtkTextBuffer *buffer,
590 ModestMsgEditWindow *userdata)
593 correct_scroll (userdata);
597 text_buffer_mark_set (GtkTextBuffer *buffer,
600 ModestMsgEditWindow *userdata)
602 gtk_text_buffer_begin_user_action (buffer);
603 gtk_text_buffer_end_user_action (buffer);
607 cut_clipboard_check (GtkTextView *text_view,
610 GtkTextBuffer *buffer;
612 buffer = gtk_text_view_get_buffer (text_view);
613 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
614 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
619 copy_clipboard_check (GtkTextView *text_view,
622 GtkTextBuffer *buffer;
624 buffer = gtk_text_view_get_buffer (text_view);
625 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
626 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
631 vadj_changed (GtkAdjustment *adj,
632 ModestMsgEditWindow *window)
634 ModestMsgEditWindowPrivate *priv;
636 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
638 if (priv->last_upper != adj->upper) {
639 priv->last_upper = adj->upper;
640 correct_scroll (window);
645 attachment_deleted (ModestAttachmentsView *attachments_view,
648 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
653 connect_signals (ModestMsgEditWindow *obj)
655 ModestMsgEditWindowPrivate *priv;
657 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
659 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
660 G_CALLBACK (text_buffer_refresh_attributes), obj);
661 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
662 G_CALLBACK (text_buffer_can_undo), obj);
663 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
664 G_CALLBACK (text_buffer_can_redo), obj);
665 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
666 G_CALLBACK (body_changed), obj);
667 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
668 G_CALLBACK (body_changed), obj);
669 g_signal_connect (G_OBJECT (obj), "window-state-event",
670 G_CALLBACK (modest_msg_edit_window_window_state_event),
672 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
673 G_CALLBACK (text_buffer_end_user_action), obj);
674 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
675 G_CALLBACK (text_buffer_mark_set), obj);
676 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
677 G_CALLBACK (text_buffer_apply_tag), obj);
678 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
679 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
680 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
681 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
682 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
683 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
685 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
686 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
688 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
689 G_CALLBACK (msg_body_focus), obj);
690 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
691 G_CALLBACK (msg_body_focus), obj);
692 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
693 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
694 "changed", G_CALLBACK (recpt_field_changed), obj);
695 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
696 "changed", G_CALLBACK (recpt_field_changed), obj);
697 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
698 "changed", G_CALLBACK (recpt_field_changed), obj);
699 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
700 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
701 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
703 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
704 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
706 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
708 G_CALLBACK (vadj_changed),
711 priv->clipboard_change_handler_id =
712 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
713 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
714 priv->default_clipboard_change_handler_id =
715 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
716 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
718 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
719 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
720 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
724 init_window (ModestMsgEditWindow *obj)
726 GtkWidget *to_caption, *subject_caption;
727 GtkWidget *main_vbox;
728 ModestMsgEditWindowPrivate *priv;
729 GtkActionGroup *action_group;
730 ModestWindowPrivate *parent_priv;
731 GdkPixbuf *window_icon = NULL;
732 GError *error = NULL;
734 GtkSizeGroup *size_group;
735 GtkWidget *subject_box;
736 GtkWidget *attachment_icon;
737 GtkWidget *window_box;
738 #if (GTK_MINOR_VERSION >= 10)
739 GdkAtom deserialize_type;
742 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
743 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
745 parent_priv->ui_manager = gtk_ui_manager_new();
746 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
747 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
749 /* Add common actions */
750 gtk_action_group_add_actions (action_group,
751 modest_msg_edit_action_entries,
752 G_N_ELEMENTS (modest_msg_edit_action_entries),
754 gtk_action_group_add_toggle_actions (action_group,
755 modest_msg_edit_toggle_action_entries,
756 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
758 gtk_action_group_add_radio_actions (action_group,
759 modest_msg_edit_alignment_radio_action_entries,
760 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
762 G_CALLBACK (modest_ui_actions_on_change_justify),
764 gtk_action_group_add_radio_actions (action_group,
765 modest_msg_edit_priority_action_entries,
766 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
768 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
770 gtk_action_group_add_radio_actions (action_group,
771 modest_msg_edit_file_format_action_entries,
772 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
773 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
774 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
776 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
777 g_object_unref (action_group);
779 /* Load the UI definition */
780 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
783 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
784 g_clear_error (&error);
787 /* Add accelerators */
788 gtk_window_add_accel_group (GTK_WINDOW (obj),
789 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
791 parent_priv->menubar = NULL;
793 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
795 /* Note: This ModestPairList* must exist for as long as the picker
796 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
797 * so it can't know how to manage its memory. */
798 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
799 MODEST_EDITABLE_ARRANGEMENT,
801 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 0.0);
802 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
803 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
805 priv->to_field = modest_recpt_editor_new ();
806 priv->cc_field = modest_recpt_editor_new ();
807 priv->bcc_field = modest_recpt_editor_new ();
808 subject_box = gtk_hbox_new (FALSE, 0);
809 priv->priority_icon = gtk_image_new ();
810 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
811 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
812 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
813 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
814 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
815 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
816 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
817 priv->add_attachment_button = gtk_button_new ();
818 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
819 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
820 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
821 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 0.5);
822 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
823 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
824 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
825 priv->attachments_view = modest_attachments_view_new (NULL);
827 priv->header_box = gtk_vbox_new (FALSE, 0);
829 hildon_button_add_title_size_group (HILDON_BUTTON (priv->from_field), size_group);
830 to_caption = modest_maemo_utils_create_captioned (size_group, _("mail_va_to"), priv->to_field);
831 priv->cc_caption = modest_maemo_utils_create_captioned (size_group, _("mail_va_cc"), priv->cc_field);
832 priv->bcc_caption = modest_maemo_utils_create_captioned (size_group, _("mail_va_hotfix1"), priv->bcc_field);
833 subject_caption = modest_maemo_utils_create_captioned (size_group, _("mail_va_subject"), subject_box);
834 priv->attachments_caption = modest_maemo_utils_create_captioned (size_group, _("mail_va_attachment"), priv->attachments_view);
835 g_object_unref (size_group);
837 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
838 hildon_button_add_value_size_group (HILDON_BUTTON (priv->from_field), size_group);
839 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
840 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
841 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
842 gtk_size_group_add_widget (size_group, priv->subject_field);
843 gtk_size_group_add_widget (size_group, priv->attachments_view);
844 g_object_unref (size_group);
846 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
847 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
848 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
849 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
850 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
851 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
852 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
855 priv->msg_body = wp_text_view_new ();
856 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
857 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
858 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
859 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
860 #if (GTK_MINOR_VERSION >= 10)
861 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
862 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
864 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
865 deserialize_type, TRUE);
867 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
869 priv->find_toolbar = hildon_find_toolbar_new (NULL);
870 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
872 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
874 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
875 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
876 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
877 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
879 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
881 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
882 priv->frame = gtk_frame_new (NULL);
883 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
885 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
886 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
887 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
889 window_box = gtk_vbox_new (FALSE, 0);
890 gtk_container_add (GTK_CONTAINER(obj), window_box);
892 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
894 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
896 /* Set window icon */
897 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
899 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
900 g_object_unref (window_icon);
905 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
907 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
909 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
910 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
911 priv->clipboard_change_handler_id))
912 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
913 priv->clipboard_change_handler_id);
914 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
915 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
916 priv->default_clipboard_change_handler_id))
917 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
918 priv->default_clipboard_change_handler_id);
920 if (priv->account_removed_handler_id &&
921 g_signal_handler_is_connected (modest_runtime_get_account_store (),
922 priv->account_removed_handler_id))
923 g_signal_handler_disconnect(modest_runtime_get_account_store (),
924 priv->account_removed_handler_id);
928 modest_msg_edit_window_finalize (GObject *obj)
930 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
932 /* Sanity check: shouldn't be needed, the window mgr should
933 call this function before */
934 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
936 if (priv->font_dialog != NULL) {
937 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
940 if (priv->clipboard_text != NULL) {
941 g_free (priv->clipboard_text);
942 priv->clipboard_text = NULL;
945 if (priv->draft_msg != NULL) {
946 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
947 if (TNY_IS_HEADER (header)) {
948 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
949 modest_window_mgr_unregister_header (mgr, header);
951 g_object_unref (priv->draft_msg);
952 priv->draft_msg = NULL;
954 if (priv->outbox_msg != NULL) {
955 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
956 if (TNY_IS_HEADER (header)) {
957 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
958 modest_window_mgr_unregister_header (mgr, header);
960 g_object_unref (priv->outbox_msg);
961 priv->outbox_msg = NULL;
963 if (priv->scroll_drag_timeout_id > 0) {
964 g_source_remove (priv->scroll_drag_timeout_id);
965 priv->scroll_drag_timeout_id = 0;
967 if (priv->clipboard_owner_idle > 0) {
968 g_source_remove (priv->clipboard_owner_idle);
969 priv->clipboard_owner_idle = 0;
971 if (priv->original_account_name)
972 g_free (priv->original_account_name);
973 g_free (priv->msg_uid);
974 g_free (priv->last_search);
975 g_slist_free (priv->font_items_group);
976 g_slist_free (priv->size_items_group);
977 g_object_unref (priv->attachments);
978 g_object_unref (priv->images);
980 /* This had to stay alive for as long as the picker that used it: */
981 modest_pair_list_free (priv->from_field_protos);
983 G_OBJECT_CLASS(parent_class)->finalize (obj);
987 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
989 GdkPixbufLoader *loader;
995 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
997 if (loader == NULL) {
1003 tny_stream_reset (TNY_STREAM (stream));
1004 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1005 GError *error = NULL;
1006 unsigned char read_buffer[128];
1008 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1010 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1015 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1017 g_object_ref (pixbuf);
1018 gdk_pixbuf_loader_close (loader, NULL);
1019 g_object_unref (loader);
1024 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1025 GdkPixbuf *new_pixbuf;
1027 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1028 gdk_pixbuf_get_width (pixbuf);
1029 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1030 g_object_unref (pixbuf);
1031 pixbuf = new_pixbuf;
1035 *stream_size = size;
1041 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1043 ModestMsgEditWindowPrivate *priv;
1046 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1048 for (iter = tny_list_create_iterator (attachments);
1049 !tny_iterator_is_done (iter);
1050 tny_iterator_next (iter)) {
1051 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1052 const gchar *cid = tny_mime_part_get_content_id (part);
1053 const gchar *mime_type = tny_mime_part_get_content_type (part);
1054 if ((cid != NULL)&&(mime_type != NULL)) {
1055 guint64 stream_size;
1056 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1057 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1060 g_object_unref (stream);
1062 if (pixbuf != NULL) {
1063 priv->images_count ++;
1064 priv->images_size += stream_size;
1065 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1066 g_object_unref (pixbuf);
1069 g_object_unref (part);
1071 g_object_unref (iter);
1075 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1077 TnyMimePart *parent = NULL;
1078 const gchar *content_type = NULL;
1079 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1081 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1083 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1084 parent = g_object_ref (msg);
1085 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1086 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1089 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1090 iter = tny_list_create_iterator (parts);
1091 while (!tny_iterator_is_done (iter)) {
1093 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1094 content_type = tny_mime_part_get_content_type (part);
1095 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1099 g_object_unref (part);
1101 tny_iterator_next (iter);
1103 g_object_unref (iter);
1104 g_object_unref (parts);
1107 if (parent != NULL) {
1108 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1111 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1112 iter = tny_list_create_iterator (parts);
1113 while (!tny_iterator_is_done (iter)) {
1115 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1116 content_type = tny_mime_part_get_content_type (part);
1117 if (content_type && g_str_has_prefix (content_type, "image/")) {
1118 tny_list_prepend (priv->images, (GObject *) part);
1120 g_object_unref (part);
1121 tny_iterator_next (iter);
1123 g_object_unref (iter);
1124 g_object_unref (parts);
1125 g_object_unref (parent);
1130 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1133 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1135 for (iter = tny_list_create_iterator (attachments) ;
1136 !tny_iterator_is_done (iter);
1137 tny_iterator_next (iter)) {
1138 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1139 const gchar *cid = tny_mime_part_get_content_id (part);
1141 char *invalid = NULL;
1142 gint int_cid = strtol (cid, &invalid, 10);
1143 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1144 priv->next_cid = int_cid + 1;
1147 g_object_unref (part);
1149 g_object_unref (iter);
1153 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1156 gchar *to, *cc, *bcc, *subject;
1158 ModestMsgEditWindowPrivate *priv;
1160 TnyHeaderFlags priority_flags;
1161 TnyFolder *msg_folder;
1162 gboolean is_html = FALSE;
1164 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1165 g_return_if_fail (TNY_IS_MSG (msg));
1167 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1169 header = tny_msg_get_header (msg);
1170 to = tny_header_dup_to (header);
1171 cc = tny_header_dup_cc (header);
1172 bcc = tny_header_dup_bcc (header);
1173 subject = tny_header_dup_subject (header);
1174 priority_flags = tny_header_get_priority (header);
1177 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1179 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1180 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1181 gtk_widget_show (priv->cc_caption);
1182 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1183 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1184 gtk_widget_hide (priv->cc_caption);
1187 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1188 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1189 gtk_widget_show (priv->bcc_caption);
1190 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1191 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1192 gtk_widget_hide (priv->bcc_caption);
1195 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1196 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1199 update_window_title (self);
1201 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1202 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1204 if ((body == NULL)||(body[0] == '\0')) {
1206 body = modest_text_utils_convert_to_html ("");
1209 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1210 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1213 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1216 /* Add attachments to the view */
1217 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1218 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1219 if (tny_list_get_length (priv->attachments) == 0) {
1220 gtk_widget_hide (priv->attachments_caption);
1222 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1223 gtk_widget_show_all (priv->attachments_caption);
1225 get_related_images (self, msg);
1226 update_next_cid (self, priv->attachments);
1227 update_next_cid (self, priv->images);
1228 replace_with_images (self, priv->images);
1230 if (preserve_is_rich && !is_html) {
1231 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1232 /* Get the default format required from configuration */
1233 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1234 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1237 /* Set the default focus depending on having already a To: field or not */
1238 if ((!to)||(*to == '\0')) {
1239 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1241 gtk_widget_grab_focus (priv->msg_body);
1244 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1246 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1247 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1249 modest_msg_edit_window_set_modified (self, FALSE);
1251 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1252 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1253 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1254 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1256 if (priv->msg_uid) {
1257 g_free (priv->msg_uid);
1258 priv->msg_uid = NULL;
1261 /* we should set a reference to the incoming message if it is a draft */
1262 msg_folder = tny_msg_get_folder (msg);
1264 if (modest_tny_folder_is_local_folder (msg_folder)) {
1265 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1266 if (type == TNY_FOLDER_TYPE_INVALID)
1267 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1269 if (type == TNY_FOLDER_TYPE_DRAFTS)
1270 priv->draft_msg = g_object_ref(msg);
1271 if (type == TNY_FOLDER_TYPE_OUTBOX)
1272 priv->outbox_msg = g_object_ref(msg);
1273 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1275 g_object_unref (msg_folder);
1285 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1288 GList *item_children, *node;
1289 GtkWidget *bin_child;
1291 bin_child = gtk_bin_get_child (GTK_BIN(item));
1293 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1295 for (node = item_children; node != NULL; node = g_list_next (node)) {
1296 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1297 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1300 g_list_free (item_children);
1304 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1307 GList *item_children, *node;
1309 box = gtk_bin_get_child (GTK_BIN (item));
1310 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1311 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1313 for (node = item_children; node != NULL; node = g_list_next (node)) {
1314 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1315 if (GTK_IS_TOGGLE_BUTTON (node->data))
1316 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1317 else if (GTK_IS_BUTTON (node->data))
1318 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1320 g_list_free (item_children);
1325 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1327 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1328 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1329 GtkWidget *placeholder;
1330 GtkWidget *tool_item;
1335 GtkWidget *sizes_menu;
1336 GtkWidget *fonts_menu;
1337 GSList *radio_group = NULL;
1338 GSList *node = NULL;
1342 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1343 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1345 /* Font color placeholder */
1346 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1347 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1350 tool_item = GTK_WIDGET (gtk_tool_item_new ());
1351 priv->font_color_button = hildon_color_button_new ();
1352 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1353 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1354 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
1355 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1356 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1357 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1358 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1360 G_CALLBACK (modest_msg_edit_window_color_button_change),
1363 /* Font size and face placeholder */
1364 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1365 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1367 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1368 priv->size_tool_button_label = gtk_label_new (NULL);
1369 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1370 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1371 size_text,"</span>", NULL);
1372 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1374 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1375 sizes_menu = gtk_menu_new ();
1376 priv->size_items_group = NULL;
1378 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1379 GtkWidget *size_menu_item;
1381 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1382 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1383 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1384 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1385 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1386 gtk_widget_show (size_menu_item);
1388 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1392 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1393 GtkWidget *item = (GtkWidget *) node->data;
1394 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1398 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1399 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1400 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1401 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1402 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1403 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1404 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1405 priv->font_size_toolitem = tool_item;
1408 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1409 priv->font_tool_button_label = gtk_label_new (NULL);
1410 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1411 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1413 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1414 fonts_menu = gtk_menu_new ();
1415 priv->font_items_group = NULL;
1417 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1418 GtkWidget *font_menu_item;
1419 GtkWidget *child_label;
1421 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1422 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1423 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1424 wp_get_font_name (font_index), "</span>", NULL);
1425 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1428 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1429 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1430 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1431 gtk_widget_show (font_menu_item);
1433 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1436 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1437 GtkWidget *item = (GtkWidget *) node->data;
1438 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1441 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1442 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1443 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1444 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1445 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1446 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1447 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1448 priv->font_face_toolitem = tool_item;
1450 /* Set expand and homogeneous for remaining items */
1451 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1452 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1453 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1454 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1455 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1456 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1457 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1458 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1459 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1461 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1462 will not show the tool items added to the placeholders) */
1463 gtk_widget_show_all (parent_priv->toolbar);
1465 /* Set the no show all *after* showing all items. We do not
1466 want the toolbar to be shown with a show all because it
1467 could go agains the gconf setting regarding showing or not
1468 the toolbar of the editor window */
1469 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1475 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1478 ModestWindowPrivate *parent_priv;
1479 ModestMsgEditWindowPrivate *priv;
1480 ModestDimmingRulesGroup *menu_rules_group = NULL;
1481 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1482 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1483 ModestWindowMgr *mgr = NULL;
1485 g_return_val_if_fail (msg, NULL);
1486 g_return_val_if_fail (account_name, NULL);
1488 mgr = modest_runtime_get_window_mgr ();
1490 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1492 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1493 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1495 /* Menubar. Update the state of some toggles */
1496 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1497 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1498 priv->from_field_protos = get_transports ();
1499 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1500 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1501 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1503 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1504 hildon_touch_selector_get_current_text
1505 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1506 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1507 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1510 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1512 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1514 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1516 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1518 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1519 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1520 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1521 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1522 /* Add common dimming rules */
1523 modest_dimming_rules_group_add_rules (menu_rules_group,
1524 modest_msg_edit_window_menu_dimming_entries,
1525 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1526 MODEST_WINDOW (obj));
1527 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1528 modest_msg_edit_window_toolbar_dimming_entries,
1529 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1530 MODEST_WINDOW (obj));
1531 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1532 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1533 MODEST_WINDOW (obj));
1534 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1535 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1536 MODEST_WINDOW (obj));
1537 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1538 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1539 MODEST_WINDOW (obj));
1540 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1541 modest_msg_edit_window_clipboard_dimming_entries,
1542 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1543 MODEST_WINDOW (obj));
1544 /* Insert dimming rules group for this window */
1545 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1546 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1547 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1548 /* Checks the dimming rules */
1549 g_object_unref (menu_rules_group);
1550 g_object_unref (toolbar_rules_group);
1551 g_object_unref (clipboard_rules_group);
1552 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1554 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1556 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1557 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1558 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1559 priv->update_caption_visibility = TRUE;
1561 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1563 /* Track account-removed signal, this window should be closed
1564 in the case we're creating a mail associated to the account
1566 priv->account_removed_handler_id =
1567 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1569 G_CALLBACK(on_account_removed),
1572 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1574 return (ModestWindow*) obj;
1578 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1580 GString **string_buffer = (GString **) user_data;
1582 *string_buffer = g_string_append (*string_buffer, buffer);
1588 * @result: A new string which should be freed with g_free().
1591 get_formatted_data (ModestMsgEditWindow *edit_window)
1593 ModestMsgEditWindowPrivate *priv;
1594 GString *string_buffer = g_string_new ("");
1596 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1598 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1600 modest_text_utils_hyperlinkify (string_buffer);
1602 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1604 return g_string_free (string_buffer, FALSE);
1609 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1612 const gchar *account_name;
1613 ModestMsgEditWindowPrivate *priv;
1614 TnyIterator *att_iter;
1616 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1618 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1620 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1621 g_return_val_if_fail (account_name, NULL);
1624 /* don't free these (except from) */
1625 data = g_slice_new0 (MsgData);
1626 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1628 data->account_name = g_strdup (account_name);
1629 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1630 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1631 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1632 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1633 if (priv->draft_msg) {
1634 data->draft_msg = g_object_ref (priv->draft_msg);
1635 } else if (priv->outbox_msg) {
1636 data->draft_msg = g_object_ref (priv->outbox_msg);
1638 data->draft_msg = NULL;
1641 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1643 gtk_text_buffer_get_bounds (buf, &b, &e);
1644 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1646 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1647 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1649 data->html_body = NULL;
1651 /* deep-copy the data */
1652 att_iter = tny_list_create_iterator (priv->attachments);
1653 data->attachments = NULL;
1654 while (!tny_iterator_is_done (att_iter)) {
1655 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1656 if (!(TNY_IS_MIME_PART(part))) {
1657 g_warning ("strange data in attachment list");
1658 g_object_unref (part);
1659 tny_iterator_next (att_iter);
1662 data->attachments = g_list_append (data->attachments,
1664 tny_iterator_next (att_iter);
1666 g_object_unref (att_iter);
1668 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1669 att_iter = tny_list_create_iterator (priv->images);
1670 data->images = NULL;
1671 while (!tny_iterator_is_done (att_iter)) {
1672 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1674 if (!(TNY_IS_MIME_PART(part))) {
1675 g_warning ("strange data in attachment list");
1676 g_object_unref (part);
1677 tny_iterator_next (att_iter);
1680 cid = tny_mime_part_get_content_id (part);
1682 gchar *image_tag_id;
1683 GtkTextTag *image_tag;
1685 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1686 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1687 g_free (image_tag_id);
1689 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1691 ((gtk_text_iter_has_tag (&iter, image_tag))||
1692 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1693 data->images = g_list_append (data->images,
1694 g_object_ref (part));
1696 g_object_unref (part);
1697 tny_iterator_next (att_iter);
1699 g_object_unref (att_iter);
1701 data->priority_flags = priv->priority_flags;
1708 unref_gobject (GObject *obj, gpointer data)
1710 if (!G_IS_OBJECT(obj))
1712 g_object_unref (obj);
1716 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1719 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1727 g_free (data->from);
1728 g_free (data->subject);
1729 g_free (data->plain_body);
1730 g_free (data->html_body);
1731 g_free (data->account_name);
1733 if (data->draft_msg != NULL) {
1734 g_object_unref (data->draft_msg);
1735 data->draft_msg = NULL;
1738 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1739 g_list_free (data->attachments);
1740 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1741 g_list_free (data->images);
1743 g_slice_free (MsgData, data);
1747 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1749 guint64 *parts_size)
1751 ModestMsgEditWindowPrivate *priv;
1753 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1755 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1757 /* TODO: add images */
1758 *parts_size += priv->images_size;
1759 *parts_count += priv->images_count;
1764 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1767 ModestMsgEditWindowPrivate *priv = NULL;
1768 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1770 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1772 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1774 return MODEST_MSG_EDIT_FORMAT_HTML;
1776 return MODEST_MSG_EDIT_FORMAT_TEXT;
1780 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1781 ModestMsgEditFormat format)
1783 ModestMsgEditWindowPrivate *priv;
1785 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1786 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1789 case MODEST_MSG_EDIT_FORMAT_HTML:
1790 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1792 case MODEST_MSG_EDIT_FORMAT_TEXT:
1793 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1796 g_return_if_reached ();
1800 ModestMsgEditFormatState *
1801 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1803 ModestMsgEditFormatState *format_state = NULL;
1804 ModestMsgEditWindowPrivate *priv;
1805 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1807 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1808 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1810 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1812 format_state = g_new0 (ModestMsgEditFormatState, 1);
1813 format_state->bold = buffer_format->bold&0x1;
1814 format_state->italics = buffer_format->italic&0x1;
1815 format_state->bullet = buffer_format->bullet&0x1;
1816 format_state->color = buffer_format->color;
1817 format_state->font_size = buffer_format->font_size;
1818 format_state->font_family = wp_get_font_name (buffer_format->font);
1819 format_state->justification = buffer_format->justification;
1820 g_free (buffer_format);
1822 return format_state;
1827 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1828 const ModestMsgEditFormatState *format_state)
1830 ModestMsgEditWindowPrivate *priv;
1831 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1832 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1833 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1834 g_return_if_fail (format_state != NULL);
1836 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1837 gtk_widget_grab_focus (priv->msg_body);
1838 buffer_format->bold = (format_state->bold != FALSE);
1839 buffer_format->italic = (format_state->italics != FALSE);
1840 buffer_format->color = format_state->color;
1841 buffer_format->font_size = format_state->font_size;
1842 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1843 buffer_format->justification = format_state->justification;
1844 buffer_format->bullet = format_state->bullet;
1846 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1848 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1849 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1850 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1851 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1852 buffer_format->cs.font = (buffer_format->font != current_format->font);
1853 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1854 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1856 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1857 if (buffer_format->cs.bold) {
1858 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1859 GINT_TO_POINTER (buffer_format->bold&0x1));
1861 if (buffer_format->cs.italic) {
1862 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1863 GINT_TO_POINTER (buffer_format->italic&0x1));
1865 if (buffer_format->cs.color) {
1866 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1867 GINT_TO_POINTER (&(buffer_format->color)));
1869 if (buffer_format->cs.font_size) {
1870 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1871 GINT_TO_POINTER (buffer_format->font_size));
1873 if (buffer_format->cs.justification) {
1874 switch (buffer_format->justification) {
1875 case GTK_JUSTIFY_LEFT:
1876 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1877 GINT_TO_POINTER(TRUE));
1879 case GTK_JUSTIFY_CENTER:
1880 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1881 GINT_TO_POINTER(TRUE));
1883 case GTK_JUSTIFY_RIGHT:
1884 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1885 GINT_TO_POINTER(TRUE));
1892 if (buffer_format->cs.font) {
1893 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1894 GINT_TO_POINTER (buffer_format->font));
1896 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1897 if (buffer_format->cs.bullet) {
1898 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1899 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1901 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1903 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1905 g_free (current_format);
1907 /* Check dimming rules */
1908 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1909 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1913 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1915 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1917 ModestWindowPrivate *parent_priv;
1918 ModestMsgEditWindowPrivate *priv;
1919 GtkWidget *new_size_menuitem;
1920 GtkWidget *new_font_menuitem;
1922 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1923 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1925 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1926 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1927 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1928 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1930 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1931 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1932 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1935 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1937 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1938 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1940 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1941 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1943 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1944 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1947 switch (buffer_format->justification)
1949 case GTK_JUSTIFY_LEFT:
1950 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1952 case GTK_JUSTIFY_CENTER:
1953 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1955 case GTK_JUSTIFY_RIGHT:
1956 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1963 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1965 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1966 G_CALLBACK (modest_msg_edit_window_color_button_change),
1968 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1969 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1970 G_CALLBACK (modest_msg_edit_window_color_button_change),
1973 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1974 buffer_format->font_size))->data);
1975 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1979 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1980 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1981 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1983 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1984 G_CALLBACK (modest_msg_edit_window_size_change),
1986 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1987 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1988 G_CALLBACK (modest_msg_edit_window_size_change),
1992 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1993 buffer_format->font))->data);
1994 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1998 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1999 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2000 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2002 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2003 G_CALLBACK (modest_msg_edit_window_font_change),
2005 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2006 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2007 G_CALLBACK (modest_msg_edit_window_font_change),
2011 g_free (buffer_format);
2015 #ifdef MODEST_HILDON_VERSION_0
2017 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2020 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2021 ModestMsgEditWindowPrivate *priv;
2022 GtkWidget *dialog = NULL;
2024 GdkColor *new_color = NULL;
2026 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2027 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2029 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2030 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2031 g_free (buffer_format);
2033 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2034 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2035 if (new_color != NULL) {
2036 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2037 (gpointer) new_color);
2040 gtk_widget_destroy (dialog);
2045 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2048 ModestMsgEditWindowPrivate *priv;
2049 GtkWidget *dialog = NULL;
2051 GdkColor *old_color = NULL;
2052 const GdkColor *new_color = NULL;
2054 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2055 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2057 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2058 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2060 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2061 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2062 if (new_color != NULL)
2063 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2065 gtk_widget_destroy (dialog);
2071 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2074 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2075 ModestMsgEditWindowPrivate *priv;
2076 GtkWidget *dialog = NULL;
2078 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2079 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2081 dialog = hildon_color_chooser_new ();
2082 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2083 g_free (buffer_format);
2085 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2087 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2088 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2091 gtk_widget_destroy (dialog);
2096 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2099 ModestMsgEditWindowPrivate *priv;
2100 GtkWidget *dialog = NULL;
2101 GdkColor *old_color = NULL;
2103 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2104 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2106 dialog = hildon_color_chooser_new ();
2107 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2109 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2111 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2112 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2114 gtk_widget_destroy (dialog);
2117 #endif /*!MODEST_HILDON_VERSION_0*/
2122 create_stream_for_uri (const gchar* uri)
2127 TnyStream *result = NULL;
2129 GnomeVFSHandle *handle = NULL;
2130 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2131 if (test == GNOME_VFS_OK) {
2132 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2133 /* Streams over OBEX (Bluetooth) are not seekable but
2134 * we expect them to be (we might need to read them
2135 * several times). So if this is a Bluetooth URI just
2136 * read the whole file into memory (this is not a fast
2137 * protocol so we can assume that these files are not
2138 * going to be very big) */
2139 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2140 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2141 TnyStream *memstream = tny_camel_mem_stream_new ();
2142 tny_stream_write_to_stream (vfssstream, memstream);
2143 g_object_unref (vfssstream);
2146 result = vfssstream;
2154 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2157 ModestMsgEditWindowPrivate *priv;
2158 GtkWidget *dialog = NULL;
2160 GSList *uris = NULL;
2161 GSList *uri_node = NULL;
2163 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2165 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2166 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2167 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2169 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2171 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2172 GTK_WINDOW (dialog));
2174 response = gtk_dialog_run (GTK_DIALOG (dialog));
2176 case GTK_RESPONSE_OK:
2177 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2182 gtk_widget_destroy (dialog);
2184 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2186 GnomeVFSHandle *handle = NULL;
2187 GnomeVFSResult result;
2188 GtkTextIter position;
2189 GtkTextMark *insert_mark;
2191 uri = (const gchar *) uri_node->data;
2192 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2193 if (result == GNOME_VFS_OK) {
2195 GnomeVFSFileInfo *info;
2196 gchar *filename, *basename, *escaped_filename;
2197 TnyMimePart *mime_part;
2199 const gchar *mime_type = NULL;
2200 GnomeVFSURI *vfs_uri;
2201 guint64 stream_size;
2203 gnome_vfs_close (handle);
2204 vfs_uri = gnome_vfs_uri_new (uri);
2206 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2207 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2208 g_free (escaped_filename);
2209 gnome_vfs_uri_unref (vfs_uri);
2210 info = gnome_vfs_file_info_new ();
2212 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2213 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2215 mime_type = gnome_vfs_file_info_get_mime_type (info);
2217 mime_part = tny_platform_factory_new_mime_part
2218 (modest_runtime_get_platform_factory ());
2220 TnyStream *stream = create_stream_for_uri (uri);
2222 if (stream == NULL) {
2224 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2226 g_object_unref (mime_part);
2227 gnome_vfs_file_info_unref (info);
2231 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2233 content_id = g_strdup_printf ("%d", priv->next_cid);
2234 tny_mime_part_set_content_id (mime_part, content_id);
2235 g_free (content_id);
2238 basename = g_path_get_basename (filename);
2239 tny_mime_part_set_filename (mime_part, basename);
2242 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2244 if (pixbuf != NULL) {
2245 priv->images_size += stream_size;
2246 priv->images_count ++;
2247 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2248 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2249 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2252 tny_list_prepend (priv->images, (GObject *) mime_part);
2253 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2255 g_object_unref (mime_part);
2256 gnome_vfs_file_info_unref (info);
2265 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2267 GtkWidget *dialog = NULL;
2269 GSList *uris = NULL;
2271 GnomeVFSFileSize total_size, allowed_size;
2272 ModestMsgEditWindowPrivate *priv;
2276 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2278 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2280 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2283 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2284 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2285 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2286 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
2288 response = gtk_dialog_run (GTK_DIALOG (dialog));
2290 case GTK_RESPONSE_OK:
2291 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2296 gtk_widget_destroy (dialog);
2298 /* allowed size is the maximum size - what's already there */
2299 modest_attachments_view_get_sizes (
2300 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2301 &att_num, &att_size);
2302 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2305 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2307 const gchar *uri = (const gchar *) uri_node->data;
2309 total_size += modest_msg_edit_window_attach_file_one
2310 (window, uri, allowed_size);
2312 if (total_size > allowed_size) {
2313 g_warning ("%s: total size: %u",
2314 __FUNCTION__, (unsigned int)total_size);
2318 allowed_size -= total_size;
2322 g_slist_foreach (uris, (GFunc) g_free, NULL);
2323 g_slist_free (uris);
2328 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2330 GnomeVFSFileSize allowed_size)
2333 GnomeVFSHandle *handle = NULL;
2334 ModestMsgEditWindowPrivate *priv;
2335 GnomeVFSResult result;
2336 GnomeVFSFileSize size = 0;
2337 g_return_val_if_fail (window, 0);
2338 g_return_val_if_fail (uri, 0);
2340 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2342 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2343 if (result == GNOME_VFS_OK) {
2344 TnyMimePart *mime_part;
2346 const gchar *mime_type = NULL;
2348 gchar *escaped_filename;
2351 GnomeVFSFileInfo *info;
2352 GnomeVFSURI *vfs_uri;
2354 gnome_vfs_close (handle);
2355 vfs_uri = gnome_vfs_uri_new (uri);
2358 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2359 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2360 g_free (escaped_filename);
2361 gnome_vfs_uri_unref (vfs_uri);
2363 info = gnome_vfs_file_info_new ();
2365 if (gnome_vfs_get_file_info (uri,
2367 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2369 mime_type = gnome_vfs_file_info_get_mime_type (info);
2370 mime_part = tny_platform_factory_new_mime_part
2371 (modest_runtime_get_platform_factory ());
2373 /* try to get the attachment's size; this may fail for weird
2374 * file systems, like obex, upnp... */
2375 if (allowed_size != 0 &&
2376 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2378 if (size > allowed_size) {
2379 modest_platform_information_banner (NULL, NULL,
2380 dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2384 g_warning ("%s: could not get attachment size", __FUNCTION__);
2386 stream = create_stream_for_uri (uri);
2388 if (stream == NULL) {
2390 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2392 g_object_unref (mime_part);
2393 gnome_vfs_file_info_unref (info);
2397 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2398 g_object_unref (stream);
2400 content_id = g_strdup_printf ("%d", priv->next_cid);
2401 tny_mime_part_set_content_id (mime_part, content_id);
2402 g_free (content_id);
2405 basename = g_path_get_basename (filename);
2406 tny_mime_part_set_filename (mime_part, basename);
2409 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2410 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2412 info->size == 0, info->size);
2413 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2414 gtk_widget_show_all (priv->attachments_caption);
2415 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2417 g_object_unref (mime_part);
2418 gnome_vfs_file_info_unref (info);
2425 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2428 ModestMsgEditWindowPrivate *priv;
2431 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2432 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2434 if (att_list == NULL) {
2435 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2437 g_object_ref (att_list);
2440 if (tny_list_get_length (att_list) == 0) {
2441 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2443 gboolean dialog_response;
2444 gchar *message = NULL;
2445 gchar *filename = NULL;
2447 if (tny_list_get_length (att_list) == 1) {
2449 iter = tny_list_create_iterator (att_list);
2450 part = (TnyMimePart *) tny_iterator_get_current (iter);
2451 g_object_unref (iter);
2452 if (TNY_IS_MSG (part)) {
2453 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2455 filename = tny_header_dup_subject (header);
2456 g_object_unref (header);
2458 if (filename == NULL) {
2459 filename = g_strdup (_("mail_va_no_subject"));
2462 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2464 g_object_unref (part);
2466 filename = g_strdup ("");
2468 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2469 tny_list_get_length (att_list)), filename);
2472 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2475 if (dialog_response != GTK_RESPONSE_OK) {
2476 g_object_unref (att_list);
2479 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
2481 for (iter = tny_list_create_iterator (att_list);
2482 !tny_iterator_is_done (iter);
2483 tny_iterator_next (iter)) {
2484 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2485 const gchar *att_id;
2486 tny_list_remove (priv->attachments, (GObject *) mime_part);
2488 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2490 if (tny_list_get_length (priv->attachments) == 0)
2491 gtk_widget_hide (priv->attachments_caption);
2492 att_id = tny_mime_part_get_content_id (mime_part);
2494 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2496 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2497 g_object_unref (mime_part);
2499 g_object_unref (iter);
2502 g_object_unref (att_list);
2504 /* if the last attachment has been removed, focus the Subject: field */
2505 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2506 gtk_widget_grab_focus (priv->subject_field);
2510 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2513 ModestMsgEditWindowPrivate *priv;
2514 GdkColor *new_color;
2515 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2517 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2518 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2521 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2523 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2525 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2527 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2532 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2535 ModestMsgEditWindowPrivate *priv;
2536 gint new_size_index;
2537 ModestMsgEditWindow *window;
2540 window = MODEST_MSG_EDIT_WINDOW (userdata);
2541 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2542 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2544 if (gtk_check_menu_item_get_active (menu_item)) {
2546 WPTextBufferFormat format;
2548 memset (&format, 0, sizeof (format));
2549 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2551 label = gtk_bin_get_child (GTK_BIN (menu_item));
2553 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2554 format.cs.font_size = TRUE;
2555 format.cs.text_position = TRUE;
2556 format.cs.font = TRUE;
2557 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2558 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2560 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2561 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2562 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2564 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2565 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2566 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2572 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2575 ModestMsgEditWindowPrivate *priv;
2576 gint new_font_index;
2577 ModestMsgEditWindow *window;
2580 window = MODEST_MSG_EDIT_WINDOW (userdata);
2581 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2582 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2584 if (gtk_check_menu_item_get_active (menu_item)) {
2587 label = gtk_bin_get_child (GTK_BIN (menu_item));
2589 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2591 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2592 GINT_TO_POINTER(new_font_index)))
2593 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2595 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2596 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2597 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2603 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2605 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2606 ModestWindowPrivate *parent_priv;
2607 ModestWindowMgr *mgr;
2608 gboolean is_fullscreen;
2609 GtkAction *fs_toggle_action;
2612 mgr = modest_runtime_get_window_mgr ();
2613 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2615 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2617 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2618 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2619 if (is_fullscreen != active)
2620 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2628 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2631 ModestMsgEditWindowPrivate *priv = NULL;
2632 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2634 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2635 if (!priv->update_caption_visibility)
2638 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2640 gtk_widget_show (priv->cc_caption);
2642 gtk_widget_hide (priv->cc_caption);
2644 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2648 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2651 ModestMsgEditWindowPrivate *priv = NULL;
2652 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2654 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2655 if (!priv->update_caption_visibility)
2658 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2660 gtk_widget_show (priv->bcc_caption);
2662 gtk_widget_hide (priv->bcc_caption);
2664 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2668 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2669 ModestRecptEditor *editor)
2671 ModestMsgEditWindowPrivate *priv;
2673 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2674 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2676 /* we check for low-mem; in that case, show a warning, and don't allow
2677 * for the addressbook
2679 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2682 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2684 if (editor == NULL) {
2685 GtkWidget *view_focus;
2686 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2688 /* This code should be kept in sync with ModestRecptEditor. The
2689 textview inside the recpt editor is the one that really gets the
2690 focus. As it's inside a scrolled window, and this one inside the
2691 hbox recpt editor inherits from, we'll need to go up in the
2692 hierarchy to know if the text view is part of the recpt editor
2693 or if it's a different text entry */
2695 if (gtk_widget_get_parent (view_focus)) {
2696 GtkWidget *first_parent;
2698 first_parent = gtk_widget_get_parent (view_focus);
2699 if (gtk_widget_get_parent (first_parent) &&
2700 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2701 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2706 editor = MODEST_RECPT_EDITOR (priv->to_field);
2710 modest_address_book_select_addresses (editor);
2715 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2717 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2719 modest_msg_edit_window_open_addressbook (window, NULL);
2723 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2724 gboolean show_toolbar)
2726 ModestWindowPrivate *parent_priv;
2727 const gchar *action_name;
2730 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2731 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2733 /* We can not just use the code of
2734 modest_msg_edit_window_setup_toolbar because it has a
2735 mixture of both initialization and creation code. */
2737 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2739 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2741 /* Update also the actions (to update the toggles in the
2742 menus), we have to do it manually because some other window
2743 of the same time could have changed it (remember that the
2744 toolbar fullscreen mode is shared by all the windows of the
2746 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2747 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2749 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2751 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2752 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2758 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2759 TnyHeaderFlags priority_flags)
2761 ModestMsgEditWindowPrivate *priv;
2762 ModestWindowPrivate *parent_priv;
2764 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2766 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2767 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2769 if (priv->priority_flags != priority_flags) {
2770 GtkAction *priority_action = NULL;
2772 priv->priority_flags = priority_flags;
2774 switch (priority_flags) {
2775 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2776 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2777 gtk_widget_show (priv->priority_icon);
2778 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2779 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2781 case TNY_HEADER_FLAG_LOW_PRIORITY:
2782 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2783 gtk_widget_show (priv->priority_icon);
2784 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2785 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2788 gtk_widget_hide (priv->priority_icon);
2789 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2790 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2793 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2794 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2799 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2802 ModestMsgEditWindowPrivate *priv;
2803 ModestWindowPrivate *parent_priv;
2804 gint current_format;
2806 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2808 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2809 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2811 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2812 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2814 if (current_format != file_format) {
2815 switch (file_format) {
2816 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2817 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2818 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2820 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2824 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2825 response = gtk_dialog_run (GTK_DIALOG (dialog));
2826 gtk_widget_destroy (dialog);
2827 if (response == GTK_RESPONSE_OK) {
2828 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2830 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2831 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2836 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2837 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2838 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2843 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2846 ModestMsgEditWindowPrivate *priv;
2847 WPTextBufferFormat oldfmt, fmt;
2848 gint old_position = 0;
2852 GdkColor *color = NULL;
2853 gboolean bold, bold_set, italic, italic_set;
2854 gboolean underline, underline_set;
2855 gboolean strikethrough, strikethrough_set;
2856 gboolean position_set;
2857 gboolean font_size_set, font_set, color_set;
2860 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2861 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2863 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2864 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2865 GTK_WINDOW(dialog));
2867 /* First we get the currently selected font information */
2868 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2870 switch (oldfmt.text_position) {
2871 case TEXT_POSITION_NORMAL:
2874 case TEXT_POSITION_SUPERSCRIPT:
2882 g_object_set (G_OBJECT (dialog),
2883 "bold", oldfmt.bold != FALSE,
2884 "bold-set", !oldfmt.cs.bold,
2885 "underline", oldfmt.underline != FALSE,
2886 "underline-set", !oldfmt.cs.underline,
2887 "italic", oldfmt.italic != FALSE,
2888 "italic-set", !oldfmt.cs.italic,
2889 "strikethrough", oldfmt.strikethrough != FALSE,
2890 "strikethrough-set", !oldfmt.cs.strikethrough,
2891 "color", &oldfmt.color,
2892 "color-set", !oldfmt.cs.color,
2893 "size", wp_font_size[oldfmt.font_size],
2894 "size-set", !oldfmt.cs.font_size,
2895 "position", old_position,
2896 "position-set", !oldfmt.cs.text_position,
2897 "family", wp_get_font_name (oldfmt.font),
2898 "family-set", !oldfmt.cs.font,
2901 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2902 GTK_WINDOW (dialog));
2903 gtk_widget_show_all (dialog);
2904 priv->font_dialog = dialog;
2905 response = gtk_dialog_run (GTK_DIALOG (dialog));
2906 priv->font_dialog = NULL;
2907 if (response == GTK_RESPONSE_OK) {
2909 g_object_get( dialog,
2911 "bold-set", &bold_set,
2912 "underline", &underline,
2913 "underline-set", &underline_set,
2915 "italic-set", &italic_set,
2916 "strikethrough", &strikethrough,
2917 "strikethrough-set", &strikethrough_set,
2919 "color-set", &color_set,
2921 "size-set", &font_size_set,
2922 "family", &font_name,
2923 "family-set", &font_set,
2924 "position", &position,
2925 "position-set", &position_set,
2930 if (response == GTK_RESPONSE_OK) {
2931 memset(&fmt, 0, sizeof(fmt));
2937 fmt.italic = italic;
2938 fmt.cs.italic = TRUE;
2940 if (underline_set) {
2941 fmt.underline = underline;
2942 fmt.cs.underline = TRUE;
2944 if (strikethrough_set) {
2945 fmt.strikethrough = strikethrough;
2946 fmt.cs.strikethrough = TRUE;
2951 ? TEXT_POSITION_NORMAL
2952 : ( ( position == 1 )
2953 ? TEXT_POSITION_SUPERSCRIPT
2954 : TEXT_POSITION_SUBSCRIPT );
2955 fmt.cs.text_position = TRUE;
2956 fmt.font_size = oldfmt.font_size;
2960 fmt.cs.color = TRUE;
2963 fmt.font = wp_get_font_index(font_name,
2968 if (font_size_set) {
2969 fmt.cs.font_size = TRUE;
2970 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2972 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2973 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2975 gtk_widget_destroy (dialog);
2977 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2981 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2983 ModestMsgEditWindowPrivate *priv;
2985 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2986 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2988 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2990 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2991 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2995 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2997 ModestMsgEditWindowPrivate *priv;
2999 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3000 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3002 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3004 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3005 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3010 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3012 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3014 priv->can_undo = can_undo;
3018 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3020 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3022 priv->can_redo = can_redo;
3026 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3028 ModestMsgEditWindowPrivate *priv;
3029 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3030 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3032 return priv->can_undo;
3036 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3038 ModestMsgEditWindowPrivate *priv;
3039 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3040 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3042 return priv->can_redo;
3047 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3050 GtkTextIter match_start, match_end;
3052 if (image_id == NULL)
3055 gtk_text_buffer_get_start_iter (buffer, &iter);
3057 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3058 GSList *tags = gtk_text_iter_get_tags (&match_start);
3060 for (node = tags; node != NULL; node = g_slist_next (node)) {
3061 GtkTextTag *tag = (GtkTextTag *) node->data;
3062 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3063 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3064 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3066 offset = gtk_text_iter_get_offset (&match_start);
3067 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3068 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3072 gtk_text_iter_forward_char (&iter);
3077 message_is_empty (ModestMsgEditWindow *window)
3079 ModestMsgEditWindowPrivate *priv = NULL;
3081 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3082 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3084 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3085 * so we can ignore markup.
3087 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3090 count = gtk_text_buffer_get_char_count (buf);
3096 msg_body_focus (GtkWidget *focus,
3097 GdkEventFocus *event,
3101 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3102 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3103 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3108 recpt_field_changed (GtkTextBuffer *buffer,
3109 ModestMsgEditWindow *editor)
3111 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3112 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3116 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3118 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3119 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3123 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3126 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3127 GtkTextBuffer *buffer;
3129 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3130 gtk_text_buffer_set_modified (buffer, modified);
3131 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3132 gtk_text_buffer_set_modified (buffer, modified);
3133 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3134 gtk_text_buffer_set_modified (buffer, modified);
3135 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3139 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3141 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3142 const char *account_name;
3143 GtkTextBuffer *buffer;
3145 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3146 if (gtk_text_buffer_get_modified (buffer))
3148 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3149 if (gtk_text_buffer_get_modified (buffer))
3151 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3152 if (gtk_text_buffer_get_modified (buffer))
3154 if (gtk_text_buffer_get_modified (priv->text_buffer))
3156 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3157 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3168 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3170 ModestMsgEditWindowPrivate *priv = NULL;
3172 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3173 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3175 /* check if there's no recipient added */
3176 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3177 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3178 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3179 /* no recipient contents, then select contacts */
3180 modest_msg_edit_window_open_addressbook (window, NULL);
3184 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3185 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3188 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3189 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3192 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3193 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3197 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3198 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3199 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3206 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3207 ModestMsgEditWindow *window)
3209 modest_msg_edit_window_offer_attach_file (window);
3213 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3215 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3217 return priv->clipboard_text;
3221 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3223 ModestMsgEditWindow *window)
3225 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3226 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3228 if (!GTK_WIDGET_VISIBLE (window))
3231 g_object_ref (window);
3232 text = gtk_clipboard_wait_for_text (selection_clipboard);
3234 if (priv->clipboard_text != NULL) {
3235 g_free (priv->clipboard_text);
3237 priv->clipboard_text = text;
3239 if (GTK_WIDGET_VISIBLE (window)) {
3240 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3242 g_object_unref (window);
3245 static gboolean clipboard_owner_change_idle (gpointer userdata)
3247 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3248 ModestMsgEditWindowPrivate *priv;
3250 gdk_threads_enter ();
3251 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3252 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3254 priv->clipboard_owner_idle = 0;
3255 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3256 gdk_threads_leave ();
3262 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3264 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3265 if (priv->clipboard_owner_idle == 0) {
3266 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3271 subject_field_move_cursor (GtkEntry *entry,
3272 GtkMovementStep step,
3277 if (!GTK_WIDGET_VISIBLE (window))
3280 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3284 update_window_title (ModestMsgEditWindow *window)
3286 ModestMsgEditWindowPrivate *priv = NULL;
3287 const gchar *subject;
3289 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3290 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3291 if (subject == NULL || subject[0] == '\0')
3292 subject = _("mail_va_new_email");
3294 gtk_window_set_title (GTK_WINDOW (window), subject);
3299 subject_field_changed (GtkEditable *editable,
3300 ModestMsgEditWindow *window)
3302 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3303 update_window_title (window);
3304 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3305 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3306 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3310 subject_field_insert_text (GtkEditable *editable,
3312 gint new_text_length,
3314 ModestMsgEditWindow *window)
3316 GString *result = g_string_new ("");
3318 gint result_len = 0;
3319 const gchar *entry_text = NULL;
3322 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3323 old_length = g_utf8_strlen (entry_text, -1);
3325 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3326 gunichar c = g_utf8_get_char_validated (current, 8);
3327 /* Invalid unichar, stop */
3333 result = g_string_append_unichar (result, c);
3337 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3338 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3341 /* Prevent endless recursion */
3342 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3343 g_signal_emit_by_name (editable, "insert-text",
3344 (gpointer) result->str, (gpointer) result->len,
3345 (gpointer) position, (gpointer) window);
3346 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3350 if (result_len + old_length > 1000) {
3351 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3352 dgettext("hildon-common-strings",
3353 "ckdg_ib_maximum_characters_reached"));
3356 g_string_free (result, TRUE);
3360 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3363 ModestMsgEditWindowPrivate *priv = NULL;
3365 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3366 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3368 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3371 gtk_widget_show_all (priv->find_toolbar);
3372 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3374 gtk_widget_hide_all (priv->find_toolbar);
3375 gtk_widget_grab_focus (priv->msg_body);
3381 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3383 GtkTextIter *match_start,
3384 GtkTextIter *match_end)
3386 GtkTextIter end_iter;
3387 gchar *str_casefold;
3390 gchar *range_casefold;
3393 gboolean result = FALSE;
3400 gtk_text_iter_forward_to_end (&end_iter);
3402 str_casefold = g_utf8_casefold (str, -1);
3403 str_chars_n = strlen (str);
3405 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3406 range_casefold = g_utf8_casefold (range_text, -1);
3407 range_chars_n = strlen (range_casefold);
3409 if (range_chars_n < str_chars_n) {
3410 g_free (str_casefold);
3411 g_free (range_text);
3412 g_free (range_casefold);
3416 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3417 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3418 if (!g_utf8_collate (range_subtext, str_casefold)) {
3419 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3421 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3422 match_start, match_end, NULL);
3423 g_free (found_text);
3425 g_free (range_subtext);
3429 g_free (str_casefold);
3430 g_free (range_text);
3431 g_free (range_casefold);
3438 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3439 ModestMsgEditWindow *window)
3441 gchar *current_search = NULL;
3442 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3444 GtkTextIter selection_start, selection_end;
3445 GtkTextIter match_start, match_end;
3446 gboolean continue_search = FALSE;
3448 if (message_is_empty (window)) {
3449 g_free (priv->last_search);
3450 priv->last_search = NULL;
3451 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3455 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3456 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3457 g_free (current_search);
3458 g_free (priv->last_search);
3459 priv->last_search = NULL;
3460 /* Information banner about empty search */
3461 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3465 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3466 continue_search = TRUE;
3468 g_free (priv->last_search);
3469 priv->last_search = g_strdup (current_search);
3472 if (continue_search) {
3473 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3474 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3475 &match_start, &match_end);
3477 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3479 GtkTextIter buffer_start;
3480 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3481 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3482 &match_start, &match_end);
3484 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3487 /* Mark as selected the string found in search */
3489 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3490 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3491 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3493 g_free (priv->last_search);
3494 priv->last_search = NULL;
3496 g_free (current_search);
3500 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3501 ModestMsgEditWindow *window)
3503 GtkToggleAction *toggle;
3504 ModestWindowPrivate *parent_priv;
3505 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3507 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3508 gtk_toggle_action_set_active (toggle, FALSE);
3512 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3514 ModestMsgEditWindowPrivate *priv;
3516 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3521 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3524 ModestMsgEditWindowPrivate *priv;
3526 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3532 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3535 ModestMsgEditWindowPrivate *priv;
3536 TnyHeader *header = NULL;
3538 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3539 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3541 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3542 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3544 if (priv->draft_msg != NULL) {
3545 g_object_unref (priv->draft_msg);
3548 if (draft != NULL) {
3549 g_object_ref (draft);
3550 header = tny_msg_get_header (draft);
3551 if (priv->msg_uid) {
3552 g_free (priv->msg_uid);
3553 priv->msg_uid = NULL;
3555 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3556 if (GTK_WIDGET_REALIZED (window))
3557 modest_window_mgr_register_window (mgr, MODEST_WINDOW (window));
3560 priv->draft_msg = draft;
3564 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3565 GtkTextIter *start, GtkTextIter *end,
3568 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3569 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3572 if (tag == NULL+13) return;
3573 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3574 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3575 replace_with_images (window, priv->images);
3580 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3583 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3585 g_return_if_fail (TNY_IS_MIME_PART (part));
3586 tny_list_prepend (priv->attachments, (GObject *) part);
3587 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3588 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3589 gtk_widget_show_all (priv->attachments_caption);
3590 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3594 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3596 ModestMsgEditWindowPrivate *priv;
3598 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3599 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3601 return priv->msg_uid;
3605 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3606 ModestMsgEditWindowWidgetType widget_type)
3608 ModestMsgEditWindowPrivate *priv;
3610 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3611 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3613 switch (widget_type) {
3614 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3615 return priv->msg_body;
3617 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3618 return priv->to_field;
3620 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3621 return priv->cc_field;
3623 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3624 return priv->bcc_field;
3626 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3627 return priv->subject_field;
3629 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3630 return priv->attachments_view;
3638 remove_tags (WPTextBuffer *buffer)
3640 GtkTextIter start, end;
3642 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3643 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3645 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3649 on_account_removed (TnyAccountStore *account_store,
3650 TnyAccount *account,
3653 /* Do nothing if it's a store account, because we use the
3654 transport to send the messages */
3655 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3656 const gchar *parent_acc = NULL;
3657 const gchar *our_acc = NULL;
3659 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3660 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3661 /* Close this window if I'm showing a message of the removed account */
3662 if (strcmp (parent_acc, our_acc) == 0)
3663 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3668 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3670 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3672 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3678 set_zoom_do_nothing (ModestWindow *window,
3684 get_zoom_do_nothing (ModestWindow *window)