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 <widgets/modest-combo-box.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <wptextview.h>
65 #include <wptextbuffer.h>
66 #include "modest-scroll-area.h"
67 #include "modest-msg-edit-window-ui-dimming.h"
69 #include "modest-hildon-includes.h"
70 #ifdef MODEST_HAVE_HILDON0_WIDGETS
71 #include <hildon-widgets/hildon-color-chooser.h>
73 #include "widgets/modest-msg-edit-window-ui.h"
74 #ifdef MODEST_HAVE_HILDON0_WIDGETS
75 #include <libgnomevfs/gnome-vfs-mime-utils.h>
77 #include <libgnomevfs/gnome-vfs-mime.h>
79 #include <modest-utils.h>
80 #include "modest-maemo-utils.h"
83 #define DEFAULT_FONT_SIZE 3
84 #define DEFAULT_FONT 2
85 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
86 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
87 #define DEFAULT_MAIN_VBOX_SPACING 6
88 #define SUBJECT_MAX_LENGTH 1000
89 #define IMAGE_MAX_WIDTH 560
90 #define DEFAULT_FONT_SCALE 1.5
92 static gboolean is_wp_text_buffer_started = FALSE;
94 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
95 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
96 static void modest_msg_edit_window_finalize (GObject *obj);
98 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
99 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
100 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
102 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
103 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
104 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
105 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
106 GtkTextIter *start, GtkTextIter *end,
108 static void text_buffer_insert_text (GtkTextBuffer *buffer,
109 GtkTextIter *location,
112 ModestMsgEditWindow *window);
113 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
114 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
115 static void subject_field_insert_text (GtkEditable *editable,
117 gint new_text_length,
119 ModestMsgEditWindow *window);
120 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
122 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
124 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
126 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
127 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
128 GdkEventWindowState *event,
130 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
131 ModestRecptEditor *editor);
132 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
133 ModestMsgEditWindow *window);
135 /* ModestWindow methods implementation */
136 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
137 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
138 gboolean show_toolbar);
139 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
141 ModestMsgEditWindow *window);
142 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
143 static void subject_field_move_cursor (GtkEntry *entry,
144 GtkMovementStep step,
148 static void update_window_title (ModestMsgEditWindow *window);
151 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
152 ModestMsgEditWindow *window);
153 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
154 ModestMsgEditWindow *window);
155 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
157 GtkTextIter *match_start,
158 GtkTextIter *match_end);
160 static void remove_tags (WPTextBuffer *buffer);
162 static void on_account_removed (TnyAccountStore *account_store,
166 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
167 static void set_zoom_do_nothing (ModestWindow *window, gdouble zoom);
168 static gdouble get_zoom_do_nothing (ModestWindow *window);
170 static void init_window (ModestMsgEditWindow *obj);
172 gboolean scroll_drag_timeout (gpointer userdata);
173 static void correct_scroll (ModestMsgEditWindow *w);
174 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
175 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
176 ModestMsgEditWindow *userdata);
177 static void text_buffer_mark_set (GtkTextBuffer *buffer,
180 ModestMsgEditWindow *userdata);
181 void vadj_changed (GtkAdjustment *adj,
182 ModestMsgEditWindow *window);
184 static ModestPair *find_transport_from_message_sender (ModestPairList *transports,
190 static void DEBUG_BUFFER (WPTextBuffer *buffer)
194 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
196 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
197 while (!gtk_text_iter_is_end (&iter)) {
198 GString *output = g_string_new ("");
199 GSList *toggled_tags;
202 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
203 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
204 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
205 GtkTextTag *tag = (GtkTextTag *) node->data;
207 g_object_get (G_OBJECT (tag), "name", &name, NULL);
208 output = g_string_append (output, name);
209 g_string_append (output, " ");
211 output = g_string_append (output, "] OPENED [ ");
212 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
213 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
214 GtkTextTag *tag = (GtkTextTag *) node->data;
216 g_object_get (G_OBJECT (tag), "name", &name, NULL);
217 output = g_string_append (output, name);
218 g_string_append (output, " ");
220 output = g_string_append (output, "]\n");
221 g_message ("%s", output->str);
222 g_string_free (output, TRUE);
223 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
225 g_message ("END BUFFER");
230 /* static gboolean */
231 /* on_key_pressed (GtkWidget *self, */
232 /* GdkEventKey *event, */
233 /* gpointer user_data); */
235 /* list my signals */
242 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
243 struct _ModestMsgEditWindowPrivate {
246 GtkWidget *header_box;
248 ModestPairList *from_field_protos;
249 GtkWidget *from_field;
250 const gchar *original_account_name;
254 GtkWidget *bcc_field;
255 GtkWidget *subject_field;
256 GtkWidget *attachments_view;
257 GtkWidget *priority_icon;
258 GtkWidget *add_attachment_button;
260 GtkWidget *cc_caption;
261 GtkWidget *bcc_caption;
262 gboolean update_caption_visibility;
263 GtkWidget *attachments_caption;
265 GtkTextBuffer *text_buffer;
267 GtkWidget *font_size_toolitem;
268 GtkWidget *font_face_toolitem;
269 GtkWidget *font_color_button;
270 GSList *font_items_group;
271 GtkWidget *font_tool_button_label;
272 GSList *size_items_group;
273 GtkWidget *size_tool_button_label;
275 GtkWidget *find_toolbar;
279 guint scroll_drag_timeout_id;
283 TnyList *attachments;
288 TnyHeaderFlags priority_flags;
290 gboolean can_undo, can_redo;
291 gulong clipboard_change_handler_id;
292 gulong default_clipboard_change_handler_id;
293 gulong account_removed_handler_id;
294 guint clipboard_owner_idle;
295 gchar *clipboard_text;
304 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
305 MODEST_TYPE_MSG_EDIT_WINDOW, \
306 ModestMsgEditWindowPrivate))
308 static GtkWindowClass *parent_class = NULL;
310 /* uncomment the following if you have defined any signals */
311 /* static guint signals[LAST_SIGNAL] = {0}; */
314 modest_msg_edit_window_get_type (void)
316 static GType my_type = 0;
318 static const GTypeInfo my_info = {
319 sizeof(ModestMsgEditWindowClass),
320 NULL, /* base init */
321 NULL, /* base finalize */
322 (GClassInitFunc) modest_msg_edit_window_class_init,
323 NULL, /* class finalize */
324 NULL, /* class data */
325 sizeof(ModestMsgEditWindow),
327 (GInstanceInitFunc) modest_msg_edit_window_init,
330 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
331 "ModestMsgEditWindow",
339 save_state (ModestWindow *self)
341 modest_widget_memory_save (modest_runtime_get_conf(),
342 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
347 restore_settings (ModestMsgEditWindow *self)
349 ModestConf *conf = NULL;
351 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
353 conf = modest_runtime_get_conf ();
354 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
355 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
356 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
357 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL));
358 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
359 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu");
360 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
361 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
363 /* set initial state of cc and bcc */
364 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
365 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
366 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
367 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
368 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
369 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
371 /* Dim at start clipboard actions */
372 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
373 gtk_action_set_sensitive (action, FALSE);
374 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
375 gtk_action_set_sensitive (action, FALSE);
376 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
377 gtk_action_set_sensitive (action, FALSE);
379 modest_widget_memory_restore (conf,
380 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
385 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
387 GObjectClass *gobject_class;
388 ModestWindowClass *modest_window_class;
389 gobject_class = (GObjectClass*) klass;
390 modest_window_class = (ModestWindowClass*) klass;
392 parent_class = g_type_class_peek_parent (klass);
393 gobject_class->finalize = modest_msg_edit_window_finalize;
395 modest_window_class->set_zoom_func = set_zoom_do_nothing;
396 modest_window_class->get_zoom_func = get_zoom_do_nothing;
397 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
398 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
399 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
400 modest_window_class->save_state_func = save_state;
401 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
403 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
407 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
409 ModestMsgEditWindowPrivate *priv;
410 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
412 priv->msg_body = NULL;
414 priv->from_field = NULL;
415 priv->to_field = NULL;
416 priv->cc_field = NULL;
417 priv->bcc_field = NULL;
418 priv->subject_field = NULL;
419 priv->attachments = TNY_LIST (tny_simple_list_new ());
420 priv->images = TNY_LIST (tny_simple_list_new ());
421 priv->images_size = 0;
422 priv->images_count = 0;
425 priv->cc_caption = NULL;
426 priv->bcc_caption = NULL;
427 priv->update_caption_visibility = FALSE;
429 priv->priority_flags = 0;
431 priv->find_toolbar = NULL;
432 priv->last_search = NULL;
434 priv->draft_msg = NULL;
435 priv->outbox_msg = NULL;
436 priv->msg_uid = NULL;
438 priv->can_undo = FALSE;
439 priv->can_redo = FALSE;
440 priv->clipboard_change_handler_id = 0;
441 priv->default_clipboard_change_handler_id = 0;
442 priv->account_removed_handler_id = 0;
443 priv->clipboard_owner_idle = 0;
444 priv->clipboard_text = NULL;
447 priv->scroll_drag_timeout_id = 0;
448 priv->last_upper = 0.0;
450 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
451 GTK_WINDOW(obj),"applications_email_editor");
453 if (!is_wp_text_buffer_started) {
454 is_wp_text_buffer_started = TRUE;
455 wp_text_buffer_library_init ();
460 hildon_program_add_window (hildon_program_get_instance(),
465 /* FIXME: this is a dup from the one in gtk/ */
468 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
470 static ModestPairList*
471 get_transports (void)
473 GSList *transports = NULL;
475 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
476 GSList *accounts = modest_account_mgr_account_names (account_mgr,
477 TRUE /* only enabled accounts. */);
479 GSList *cursor = accounts;
481 gchar *account_name = cursor->data;
482 gchar *from_string = NULL;
484 from_string = modest_account_mgr_get_from_string (account_mgr,
488 if (from_string && account_name) {
489 gchar *name = account_name;
490 ModestPair *pair = modest_pair_new ((gpointer) name,
491 (gpointer) from_string , TRUE);
492 transports = g_slist_prepend (transports, pair);
495 cursor = cursor->next;
497 g_slist_free (accounts); /* only free the accounts, not the elements,
498 * because they are used in the pairlist */
503 * Search an (account, address) ModestPairList for a pair whose
504 * address matches the one in the From: header of a TnyMsg
506 * @result: A ModestPair * with a matching address, or NULL if none found
509 find_transport_from_message_sender (ModestPairList *transports, TnyMsg *msg)
511 ModestPair *account_pair = NULL;
515 g_return_val_if_fail (transports, NULL);
516 g_return_val_if_fail (msg, NULL);
518 header = tny_msg_get_header (msg);
520 if (header != NULL && (from = tny_header_dup_from (header))) {
524 from_addr = modest_text_utils_get_email_address (from);
526 for (iter = transports; iter && !account_pair; iter = iter->next) {
527 ModestPair *pair = (ModestPair *) iter->data;
528 char *account_addr = modest_text_utils_get_email_address ((char *) pair->second);
529 if (account_addr && !strcasecmp(from_addr, account_addr)) {
532 g_free (account_addr);
538 g_object_unref (header);
543 static void window_focus (GtkWindow *window,
547 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
551 scroll_drag_timeout (gpointer userdata)
553 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
554 ModestMsgEditWindowPrivate *priv;
556 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
558 correct_scroll_without_drag_check (win, TRUE);
560 priv->scroll_drag_timeout_id = 0;
566 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
568 ModestMsgEditWindowPrivate *priv;
571 GdkRectangle rectangle;
577 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
579 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
582 insert = gtk_text_buffer_get_insert (priv->text_buffer);
583 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
585 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
586 vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll));
587 offset = priv->msg_body->allocation.y;
589 new_value = vadj->value;
591 if ((offset + rectangle.y + rectangle.height) >
592 ((gint) (vadj->value +vadj->page_size))) {
593 new_value = (offset + rectangle.y) - vadj->page_size * 0.25;
594 if (new_value > vadj->upper - vadj->page_size)
595 new_value = vadj->upper - vadj->page_size;
596 } else if ((offset + rectangle.y) < ((gint) vadj->value)) {
597 new_value = (offset + rectangle.y - vadj->page_size * 0.75);
598 if (((gint) (new_value + vadj->page_size)) < (offset + rectangle.y + rectangle.height))
599 new_value = offset + rectangle.y + rectangle.height - (gint) vadj->page_size;
602 if (new_value > vadj->value)
603 new_value = vadj->value;
606 if (vadj->value != new_value) {
607 g_signal_emit_by_name (GTK_TEXT_VIEW(priv->msg_body)->layout,
609 vadj->value = new_value;
610 gtk_adjustment_value_changed (vadj);
611 /* invalidate body */
612 window = gtk_widget_get_parent_window (priv->msg_body);
614 gdk_window_invalidate_rect (window, NULL, TRUE);
620 correct_scroll (ModestMsgEditWindow *w)
622 ModestMsgEditWindowPrivate *priv;
624 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
625 if (gtk_grab_get_current () == priv->msg_body) {
626 if (priv->scroll_drag_timeout_id == 0) {
627 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
633 correct_scroll_without_drag_check (w, TRUE);
637 text_buffer_end_user_action (GtkTextBuffer *buffer,
638 ModestMsgEditWindow *userdata)
641 correct_scroll (userdata);
645 text_buffer_mark_set (GtkTextBuffer *buffer,
648 ModestMsgEditWindow *userdata)
650 gtk_text_buffer_begin_user_action (buffer);
651 gtk_text_buffer_end_user_action (buffer);
655 cut_clipboard_check (GtkTextView *text_view,
658 GtkTextBuffer *buffer;
660 buffer = gtk_text_view_get_buffer (text_view);
661 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
662 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
667 copy_clipboard_check (GtkTextView *text_view,
670 GtkTextBuffer *buffer;
672 buffer = gtk_text_view_get_buffer (text_view);
673 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
674 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
678 void vadj_changed (GtkAdjustment *adj,
679 ModestMsgEditWindow *window)
681 ModestMsgEditWindowPrivate *priv;
683 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
685 if (priv->last_upper != adj->upper) {
686 priv->last_upper = adj->upper;
687 correct_scroll (window);
692 connect_signals (ModestMsgEditWindow *obj)
694 ModestMsgEditWindowPrivate *priv;
696 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
698 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
699 G_CALLBACK (text_buffer_refresh_attributes), obj);
700 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
701 G_CALLBACK (text_buffer_can_undo), obj);
702 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
703 G_CALLBACK (text_buffer_can_redo), obj);
704 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
705 G_CALLBACK (body_changed), obj);
706 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
707 G_CALLBACK (body_changed), obj);
708 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
709 G_CALLBACK (text_buffer_insert_text), obj);
710 g_signal_connect (G_OBJECT (obj), "window-state-event",
711 G_CALLBACK (modest_msg_edit_window_window_state_event),
713 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
714 G_CALLBACK (text_buffer_end_user_action), obj);
715 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
716 G_CALLBACK (text_buffer_mark_set), obj);
717 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
718 G_CALLBACK (text_buffer_apply_tag), obj);
719 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
720 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
721 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
722 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
723 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
724 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
726 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
727 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
729 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
730 G_CALLBACK (msg_body_focus), obj);
731 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
732 G_CALLBACK (msg_body_focus), obj);
733 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
734 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
735 "changed", G_CALLBACK (recpt_field_changed), obj);
736 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
737 "changed", G_CALLBACK (recpt_field_changed), obj);
738 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
739 "changed", G_CALLBACK (recpt_field_changed), obj);
740 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
741 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
742 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
744 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
745 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
747 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
749 G_CALLBACK (vadj_changed),
752 priv->clipboard_change_handler_id =
753 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
754 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
755 priv->default_clipboard_change_handler_id =
756 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
757 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
759 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
760 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
765 init_window (ModestMsgEditWindow *obj)
767 GtkWidget *from_caption, *to_caption, *subject_caption;
768 GtkWidget *main_vbox;
769 ModestMsgEditWindowPrivate *priv;
770 GtkActionGroup *action_group;
771 ModestWindowPrivate *parent_priv;
772 GdkPixbuf *window_icon = NULL;
773 GError *error = NULL;
775 GtkSizeGroup *size_group;
776 GtkWidget *subject_box;
777 GtkWidget *attachment_icon;
778 GtkWidget *window_box;
779 #if (GTK_MINOR_VERSION >= 10)
780 GdkAtom deserialize_type;
782 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
783 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
785 parent_priv->ui_manager = gtk_ui_manager_new();
786 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
787 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
789 /* Add common actions */
790 gtk_action_group_add_actions (action_group,
791 modest_msg_edit_action_entries,
792 G_N_ELEMENTS (modest_msg_edit_action_entries),
794 gtk_action_group_add_toggle_actions (action_group,
795 modest_msg_edit_toggle_action_entries,
796 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
798 gtk_action_group_add_radio_actions (action_group,
799 modest_msg_edit_alignment_radio_action_entries,
800 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
802 G_CALLBACK (modest_ui_actions_on_change_justify),
804 gtk_action_group_add_radio_actions (action_group,
805 modest_msg_edit_priority_action_entries,
806 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
808 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
810 gtk_action_group_add_radio_actions (action_group,
811 modest_msg_edit_file_format_action_entries,
812 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
813 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
814 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
816 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
817 g_object_unref (action_group);
819 /* Load the UI definition */
820 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
823 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
824 g_clear_error (&error);
827 /* Add accelerators */
828 gtk_window_add_accel_group (GTK_WINDOW (obj),
829 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
831 parent_priv->menubar = NULL;
833 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
835 /* Note: This ModestPairList* must exist for as long as the combo
836 * that uses it, because the ModestComboBox uses the ID opaquely,
837 * so it can't know how to manage its memory. */
838 priv->from_field = modest_combo_box_new (NULL, g_str_equal);
840 priv->to_field = modest_recpt_editor_new ();
841 priv->cc_field = modest_recpt_editor_new ();
842 priv->bcc_field = modest_recpt_editor_new ();
843 subject_box = gtk_hbox_new (FALSE, 0);
844 priv->priority_icon = gtk_image_new ();
845 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
846 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
847 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
848 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
849 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
850 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
851 priv->add_attachment_button = gtk_button_new ();
852 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
853 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
854 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
855 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
856 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
857 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
858 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
859 priv->attachments_view = modest_attachments_view_new (NULL);
861 priv->header_box = gtk_vbox_new (FALSE, 0);
863 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
864 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
865 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
866 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
867 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
868 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
869 g_object_unref (size_group);
871 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
872 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
873 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
874 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
875 gtk_size_group_add_widget (size_group, priv->subject_field);
876 gtk_size_group_add_widget (size_group, priv->attachments_view);
877 g_object_unref (size_group);
879 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
880 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
881 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
882 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
883 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
884 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
885 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
888 priv->msg_body = wp_text_view_new ();
889 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
890 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
891 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
892 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
893 #if (GTK_MINOR_VERSION >= 10)
894 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
895 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
897 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
898 deserialize_type, TRUE);
900 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
902 priv->find_toolbar = hildon_find_toolbar_new (NULL);
903 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
905 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
907 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
908 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
909 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
910 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
912 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
914 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
915 priv->frame = gtk_frame_new (NULL);
916 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
918 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
919 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
920 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
922 window_box = gtk_vbox_new (FALSE, 0);
923 gtk_container_add (GTK_CONTAINER(obj), window_box);
925 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
927 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
929 /* Set window icon */
930 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
932 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
933 g_object_unref (window_icon);
938 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
940 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
942 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
943 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
944 priv->clipboard_change_handler_id))
945 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
946 priv->clipboard_change_handler_id);
947 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
948 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
949 priv->default_clipboard_change_handler_id))
950 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
951 priv->default_clipboard_change_handler_id);
953 if (priv->account_removed_handler_id &&
954 g_signal_handler_is_connected (modest_runtime_get_account_store (),
955 priv->account_removed_handler_id))
956 g_signal_handler_disconnect(modest_runtime_get_account_store (),
957 priv->account_removed_handler_id);
961 modest_msg_edit_window_finalize (GObject *obj)
963 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
965 /* Sanity check: shouldn't be needed, the window mgr should
966 call this function before */
967 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
969 if (priv->clipboard_text != NULL) {
970 g_free (priv->clipboard_text);
971 priv->clipboard_text = NULL;
974 if (priv->draft_msg != NULL) {
975 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
976 if (TNY_IS_HEADER (header)) {
977 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
978 modest_window_mgr_unregister_header (mgr, header);
980 g_object_unref (priv->draft_msg);
981 priv->draft_msg = NULL;
983 if (priv->outbox_msg != NULL) {
984 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
985 if (TNY_IS_HEADER (header)) {
986 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
987 modest_window_mgr_unregister_header (mgr, header);
989 g_object_unref (priv->outbox_msg);
990 priv->outbox_msg = NULL;
992 if (priv->scroll_drag_timeout_id > 0) {
993 g_source_remove (priv->scroll_drag_timeout_id);
994 priv->scroll_drag_timeout_id = 0;
996 if (priv->clipboard_owner_idle > 0) {
997 g_source_remove (priv->clipboard_owner_idle);
998 priv->clipboard_owner_idle = 0;
1000 g_free (priv->msg_uid);
1001 g_free (priv->last_search);
1002 g_slist_free (priv->font_items_group);
1003 g_slist_free (priv->size_items_group);
1004 g_object_unref (priv->attachments);
1005 g_object_unref (priv->images);
1007 /* This had to stay alive for as long as the combobox that used it: */
1008 modest_pair_list_free (priv->from_field_protos);
1010 G_OBJECT_CLASS(parent_class)->finalize (obj);
1014 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
1016 GdkPixbufLoader *loader;
1022 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1024 if (loader == NULL) {
1030 tny_stream_reset (TNY_STREAM (stream));
1031 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1032 GError *error = NULL;
1033 unsigned char read_buffer[128];
1035 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1037 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1042 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1044 g_object_ref (pixbuf);
1045 gdk_pixbuf_loader_close (loader, NULL);
1046 g_object_unref (loader);
1051 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1052 GdkPixbuf *new_pixbuf;
1054 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1055 gdk_pixbuf_get_width (pixbuf);
1056 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1057 g_object_unref (pixbuf);
1058 pixbuf = new_pixbuf;
1062 *stream_size = size;
1068 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1070 ModestMsgEditWindowPrivate *priv;
1073 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1075 for (iter = tny_list_create_iterator (attachments);
1076 !tny_iterator_is_done (iter);
1077 tny_iterator_next (iter)) {
1078 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1079 const gchar *cid = tny_mime_part_get_content_id (part);
1080 const gchar *mime_type = tny_mime_part_get_content_type (part);
1081 if ((cid != NULL)&&(mime_type != NULL)) {
1082 guint64 stream_size;
1083 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1084 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1087 g_object_unref (stream);
1089 if (pixbuf != NULL) {
1090 priv->images_count ++;
1091 priv->images_size += stream_size;
1092 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1093 g_object_unref (pixbuf);
1096 g_object_unref (part);
1098 g_object_unref (iter);
1102 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1104 TnyMimePart *parent = NULL;
1105 const gchar *content_type = NULL;
1106 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1108 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1110 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1111 parent = g_object_ref (msg);
1112 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1113 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1116 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1117 iter = tny_list_create_iterator (parts);
1118 while (!tny_iterator_is_done (iter)) {
1120 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1121 content_type = tny_mime_part_get_content_type (part);
1122 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1126 g_object_unref (part);
1128 tny_iterator_next (iter);
1130 g_object_unref (iter);
1131 g_object_unref (parts);
1134 if (parent != NULL) {
1135 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1138 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1139 iter = tny_list_create_iterator (parts);
1140 while (!tny_iterator_is_done (iter)) {
1142 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1143 content_type = tny_mime_part_get_content_type (part);
1144 if (content_type && g_str_has_prefix (content_type, "image/")) {
1145 tny_list_prepend (priv->images, (GObject *) part);
1147 g_object_unref (part);
1148 tny_iterator_next (iter);
1150 g_object_unref (iter);
1151 g_object_unref (parts);
1152 g_object_unref (parent);
1157 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1160 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1162 for (iter = tny_list_create_iterator (attachments) ;
1163 !tny_iterator_is_done (iter);
1164 tny_iterator_next (iter)) {
1165 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1166 const gchar *cid = tny_mime_part_get_content_id (part);
1168 char *invalid = NULL;
1169 gint int_cid = strtol (cid, &invalid, 10);
1170 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1171 priv->next_cid = int_cid + 1;
1174 g_object_unref (part);
1176 g_object_unref (iter);
1180 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1183 gchar *to, *cc, *bcc, *subject;
1185 ModestMsgEditWindowPrivate *priv;
1187 TnyHeaderFlags priority_flags;
1188 TnyFolder *msg_folder;
1189 gboolean is_html = FALSE;
1191 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1192 g_return_if_fail (TNY_IS_MSG (msg));
1194 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1196 header = tny_msg_get_header (msg);
1197 to = tny_header_dup_to (header);
1198 cc = tny_header_dup_cc (header);
1199 bcc = tny_header_dup_bcc (header);
1200 subject = tny_header_dup_subject (header);
1201 priority_flags = tny_header_get_priority (header);
1204 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1206 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1207 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1208 gtk_widget_show (priv->cc_caption);
1209 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1210 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1211 gtk_widget_hide (priv->cc_caption);
1214 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1215 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1216 gtk_widget_show (priv->bcc_caption);
1217 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1218 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1219 gtk_widget_hide (priv->bcc_caption);
1222 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1223 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1226 update_window_title (self);
1228 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1229 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1231 if ((body == NULL)||(body[0] == '\0')) {
1233 body = modest_text_utils_convert_to_html ("");
1236 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1237 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1240 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1243 /* Add attachments to the view */
1244 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1245 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1246 if (tny_list_get_length (priv->attachments) == 0) {
1247 gtk_widget_hide (priv->attachments_caption);
1249 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1250 gtk_widget_show_all (priv->attachments_caption);
1252 get_related_images (self, msg);
1253 update_next_cid (self, priv->attachments);
1254 update_next_cid (self, priv->images);
1255 replace_with_images (self, priv->images);
1257 if (preserve_is_rich && !is_html) {
1258 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1259 /* Get the default format required from configuration */
1260 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1261 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1264 /* Set the default focus depending on having already a To: field or not */
1265 if ((!to)||(*to == '\0')) {
1266 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1268 gtk_widget_grab_focus (priv->msg_body);
1271 /* TODO: lower priority, select in the From: combo to the
1272 value that comes from msg <- not sure, should it be
1275 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1277 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1278 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1280 modest_msg_edit_window_set_modified (self, FALSE);
1282 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1283 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1284 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1285 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1287 if (priv->msg_uid) {
1288 g_free (priv->msg_uid);
1289 priv->msg_uid = NULL;
1292 /* we should set a reference to the incoming message if it is a draft */
1293 msg_folder = tny_msg_get_folder (msg);
1295 if (modest_tny_folder_is_local_folder (msg_folder)) {
1296 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1297 if (type == TNY_FOLDER_TYPE_INVALID)
1298 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1300 if (type == TNY_FOLDER_TYPE_DRAFTS)
1301 priv->draft_msg = g_object_ref(msg);
1302 if (type == TNY_FOLDER_TYPE_OUTBOX)
1303 priv->outbox_msg = g_object_ref(msg);
1304 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1306 g_object_unref (msg_folder);
1316 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1319 GList *item_children, *node;
1320 GtkWidget *bin_child;
1322 bin_child = gtk_bin_get_child (GTK_BIN(item));
1324 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1326 for (node = item_children; node != NULL; node = g_list_next (node)) {
1327 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1328 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1331 g_list_free (item_children);
1335 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1338 GList *item_children, *node;
1340 box = gtk_bin_get_child (GTK_BIN (item));
1341 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1342 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1344 for (node = item_children; node != NULL; node = g_list_next (node)) {
1345 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1346 if (GTK_IS_TOGGLE_BUTTON (node->data))
1347 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1348 else if (GTK_IS_BUTTON (node->data))
1349 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1351 g_list_free (item_children);
1356 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1358 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1359 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1360 GtkWidget *placeholder;
1361 GtkWidget *tool_item;
1366 GtkWidget *sizes_menu;
1367 GtkWidget *fonts_menu;
1368 GSList *radio_group = NULL;
1369 GSList *node = NULL;
1373 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1374 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1376 /* Font color placeholder */
1377 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1378 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1381 tool_item = GTK_WIDGET (gtk_tool_item_new ());
1382 priv->font_color_button = hildon_color_button_new ();
1383 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1384 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1385 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
1386 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1387 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1388 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1389 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1391 G_CALLBACK (modest_msg_edit_window_color_button_change),
1394 /* Font size and face placeholder */
1395 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1396 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1398 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1399 priv->size_tool_button_label = gtk_label_new (NULL);
1400 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1401 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1402 size_text,"</span>", NULL);
1403 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1405 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1406 sizes_menu = gtk_menu_new ();
1407 priv->size_items_group = NULL;
1409 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1410 GtkWidget *size_menu_item;
1412 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1413 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1414 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1415 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1416 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1417 gtk_widget_show (size_menu_item);
1419 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1423 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1424 GtkWidget *item = (GtkWidget *) node->data;
1425 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1429 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1430 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1431 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1432 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1433 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1434 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1435 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1436 priv->font_size_toolitem = tool_item;
1439 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1440 priv->font_tool_button_label = gtk_label_new (NULL);
1441 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1442 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1444 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1445 fonts_menu = gtk_menu_new ();
1446 priv->font_items_group = NULL;
1448 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1449 GtkWidget *font_menu_item;
1450 GtkWidget *child_label;
1452 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1453 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1454 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1455 wp_get_font_name (font_index), "</span>", NULL);
1456 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1459 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1460 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1461 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1462 gtk_widget_show (font_menu_item);
1464 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1467 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1468 GtkWidget *item = (GtkWidget *) node->data;
1469 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1472 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1473 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1474 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1475 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1476 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1477 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1478 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1479 priv->font_face_toolitem = tool_item;
1481 /* Set expand and homogeneous for remaining items */
1482 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1483 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1484 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1485 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1486 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1487 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1488 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1489 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1490 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1492 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1493 will not show the tool items added to the placeholders) */
1494 gtk_widget_show_all (parent_priv->toolbar);
1496 /* Set the no show all *after* showing all items. We do not
1497 want the toolbar to be shown with a show all because it
1498 could go agains the gconf setting regarding showing or not
1499 the toolbar of the editor window */
1500 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1506 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1509 ModestWindowPrivate *parent_priv;
1510 ModestMsgEditWindowPrivate *priv;
1511 ModestPair *account_pair = NULL;
1512 ModestDimmingRulesGroup *menu_rules_group = NULL;
1513 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1514 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1515 ModestWindowMgr *mgr = NULL;
1517 g_return_val_if_fail (msg, NULL);
1518 g_return_val_if_fail (account_name, NULL);
1520 mgr = modest_runtime_get_window_mgr ();
1522 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1524 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1525 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1527 /* Menubar. Update the state of some toggles */
1528 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1529 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1530 priv->from_field_protos = get_transports ();
1531 modest_combo_box_set_pair_list (MODEST_COMBO_BOX (priv->from_field), priv->from_field_protos);
1532 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1533 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1536 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1538 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1540 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1542 account_pair = find_transport_from_message_sender (priv->from_field_protos, msg);
1543 if (account_pair == NULL) {
1544 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
1546 if (account_pair != NULL)
1547 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
1549 priv->original_account_name = account_pair ? (const gchar *) account_pair->first : NULL;
1551 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1552 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1553 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1554 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1555 /* Add common dimming rules */
1556 modest_dimming_rules_group_add_rules (menu_rules_group,
1557 modest_msg_edit_window_menu_dimming_entries,
1558 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1559 MODEST_WINDOW (obj));
1560 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1561 modest_msg_edit_window_toolbar_dimming_entries,
1562 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1563 MODEST_WINDOW (obj));
1564 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1565 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1566 MODEST_WINDOW (obj));
1567 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1568 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1569 MODEST_WINDOW (obj));
1570 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1571 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1572 MODEST_WINDOW (obj));
1573 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1574 modest_msg_edit_window_clipboard_dimming_entries,
1575 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1576 MODEST_WINDOW (obj));
1577 /* Insert dimming rules group for this window */
1578 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1579 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1580 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1581 /* Checks the dimming rules */
1582 g_object_unref (menu_rules_group);
1583 g_object_unref (toolbar_rules_group);
1584 g_object_unref (clipboard_rules_group);
1585 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1587 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1589 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1590 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1591 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1592 priv->update_caption_visibility = TRUE;
1594 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1596 /* Track account-removed signal, this window should be closed
1597 in the case we're creating a mail associated to the account
1599 priv->account_removed_handler_id =
1600 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1602 G_CALLBACK(on_account_removed),
1605 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1607 return (ModestWindow*) obj;
1611 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1613 GString **string_buffer = (GString **) user_data;
1615 *string_buffer = g_string_append (*string_buffer, buffer);
1621 * @result: A new string which should be freed with g_free().
1624 get_formatted_data (ModestMsgEditWindow *edit_window)
1626 ModestMsgEditWindowPrivate *priv;
1627 GString *string_buffer = g_string_new ("");
1629 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1631 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1633 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1635 return g_string_free (string_buffer, FALSE);
1640 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1643 const gchar *account_name;
1644 ModestMsgEditWindowPrivate *priv;
1645 TnyIterator *att_iter;
1647 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1649 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1651 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1652 g_return_val_if_fail (account_name, NULL);
1655 /* don't free these (except from) */
1656 data = g_slice_new0 (MsgData);
1657 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1659 data->account_name = g_strdup (account_name);
1660 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1661 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1662 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1663 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1664 if (priv->draft_msg) {
1665 data->draft_msg = g_object_ref (priv->draft_msg);
1666 } else if (priv->outbox_msg) {
1667 data->draft_msg = g_object_ref (priv->outbox_msg);
1669 data->draft_msg = NULL;
1672 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1674 gtk_text_buffer_get_bounds (buf, &b, &e);
1675 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1677 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1678 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1680 data->html_body = NULL;
1682 /* deep-copy the data */
1683 att_iter = tny_list_create_iterator (priv->attachments);
1684 data->attachments = NULL;
1685 while (!tny_iterator_is_done (att_iter)) {
1686 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1687 if (!(TNY_IS_MIME_PART(part))) {
1688 g_warning ("strange data in attachment list");
1689 g_object_unref (part);
1690 tny_iterator_next (att_iter);
1693 data->attachments = g_list_append (data->attachments,
1695 tny_iterator_next (att_iter);
1697 g_object_unref (att_iter);
1699 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1700 att_iter = tny_list_create_iterator (priv->images);
1701 data->images = NULL;
1702 while (!tny_iterator_is_done (att_iter)) {
1703 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1705 if (!(TNY_IS_MIME_PART(part))) {
1706 g_warning ("strange data in attachment list");
1707 g_object_unref (part);
1708 tny_iterator_next (att_iter);
1711 cid = tny_mime_part_get_content_id (part);
1713 gchar *image_tag_id;
1714 GtkTextTag *image_tag;
1716 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1717 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1718 g_free (image_tag_id);
1720 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1722 ((gtk_text_iter_has_tag (&iter, image_tag))||
1723 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1724 data->images = g_list_append (data->images,
1725 g_object_ref (part));
1727 g_object_unref (part);
1728 tny_iterator_next (att_iter);
1730 g_object_unref (att_iter);
1732 data->priority_flags = priv->priority_flags;
1739 unref_gobject (GObject *obj, gpointer data)
1741 if (!G_IS_OBJECT(obj))
1743 g_object_unref (obj);
1747 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1750 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1758 g_free (data->from);
1759 g_free (data->subject);
1760 g_free (data->plain_body);
1761 g_free (data->html_body);
1762 g_free (data->account_name);
1764 if (data->draft_msg != NULL) {
1765 g_object_unref (data->draft_msg);
1766 data->draft_msg = NULL;
1769 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1770 g_list_free (data->attachments);
1771 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1772 g_list_free (data->images);
1774 g_slice_free (MsgData, data);
1778 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1780 guint64 *parts_size)
1782 ModestMsgEditWindowPrivate *priv;
1784 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1786 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1788 /* TODO: add images */
1789 *parts_size += priv->images_size;
1790 *parts_count += priv->images_count;
1795 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1798 ModestMsgEditWindowPrivate *priv = NULL;
1799 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1801 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1803 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1805 return MODEST_MSG_EDIT_FORMAT_HTML;
1807 return MODEST_MSG_EDIT_FORMAT_TEXT;
1811 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1812 ModestMsgEditFormat format)
1814 ModestMsgEditWindowPrivate *priv;
1816 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1817 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1820 case MODEST_MSG_EDIT_FORMAT_HTML:
1821 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1823 case MODEST_MSG_EDIT_FORMAT_TEXT:
1824 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1827 g_return_if_reached ();
1831 ModestMsgEditFormatState *
1832 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1834 ModestMsgEditFormatState *format_state = NULL;
1835 ModestMsgEditWindowPrivate *priv;
1836 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1838 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1839 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1841 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1843 format_state = g_new0 (ModestMsgEditFormatState, 1);
1844 format_state->bold = buffer_format->bold&0x1;
1845 format_state->italics = buffer_format->italic&0x1;
1846 format_state->bullet = buffer_format->bullet&0x1;
1847 format_state->color = buffer_format->color;
1848 format_state->font_size = buffer_format->font_size;
1849 format_state->font_family = wp_get_font_name (buffer_format->font);
1850 format_state->justification = buffer_format->justification;
1851 g_free (buffer_format);
1853 return format_state;
1858 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1859 const ModestMsgEditFormatState *format_state)
1861 ModestMsgEditWindowPrivate *priv;
1862 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1863 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1864 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1865 g_return_if_fail (format_state != NULL);
1867 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1868 gtk_widget_grab_focus (priv->msg_body);
1869 buffer_format->bold = (format_state->bold != FALSE);
1870 buffer_format->italic = (format_state->italics != FALSE);
1871 buffer_format->color = format_state->color;
1872 buffer_format->font_size = format_state->font_size;
1873 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1874 buffer_format->justification = format_state->justification;
1875 buffer_format->bullet = format_state->bullet;
1877 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1879 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1880 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1881 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1882 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1883 buffer_format->cs.font = (buffer_format->font != current_format->font);
1884 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1885 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1887 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1888 if (buffer_format->cs.bold) {
1889 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1890 GINT_TO_POINTER (buffer_format->bold&0x1));
1892 if (buffer_format->cs.italic) {
1893 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1894 GINT_TO_POINTER (buffer_format->italic&0x1));
1896 if (buffer_format->cs.color) {
1897 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1898 GINT_TO_POINTER (&(buffer_format->color)));
1900 if (buffer_format->cs.font_size) {
1901 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1902 GINT_TO_POINTER (buffer_format->font_size));
1904 if (buffer_format->cs.justification) {
1905 switch (buffer_format->justification) {
1906 case GTK_JUSTIFY_LEFT:
1907 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1908 GINT_TO_POINTER(TRUE));
1910 case GTK_JUSTIFY_CENTER:
1911 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1912 GINT_TO_POINTER(TRUE));
1914 case GTK_JUSTIFY_RIGHT:
1915 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1916 GINT_TO_POINTER(TRUE));
1923 if (buffer_format->cs.font) {
1924 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1925 GINT_TO_POINTER (buffer_format->font));
1927 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1928 if (buffer_format->cs.bullet) {
1929 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1930 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1932 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1934 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1936 g_free (current_format);
1941 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1943 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1945 ModestWindowPrivate *parent_priv;
1946 ModestMsgEditWindowPrivate *priv;
1947 GtkWidget *new_size_menuitem;
1948 GtkWidget *new_font_menuitem;
1950 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1951 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1953 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1954 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1955 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1956 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1958 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1959 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1960 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1963 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1965 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1966 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1968 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1969 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1971 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1972 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1975 switch (buffer_format->justification)
1977 case GTK_JUSTIFY_LEFT:
1978 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1980 case GTK_JUSTIFY_CENTER:
1981 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1983 case GTK_JUSTIFY_RIGHT:
1984 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1991 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1993 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1994 G_CALLBACK (modest_msg_edit_window_color_button_change),
1996 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1997 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1998 G_CALLBACK (modest_msg_edit_window_color_button_change),
2001 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
2002 buffer_format->font_size))->data);
2003 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
2007 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
2008 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2009 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2011 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
2012 G_CALLBACK (modest_msg_edit_window_size_change),
2014 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
2015 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
2016 G_CALLBACK (modest_msg_edit_window_size_change),
2020 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
2021 buffer_format->font))->data);
2022 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
2026 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2027 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2028 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2030 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2031 G_CALLBACK (modest_msg_edit_window_font_change),
2033 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2034 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2035 G_CALLBACK (modest_msg_edit_window_font_change),
2039 g_free (buffer_format);
2043 #ifdef MODEST_HILDON_VERSION_0
2045 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2048 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2049 ModestMsgEditWindowPrivate *priv;
2050 GtkWidget *dialog = NULL;
2052 GdkColor *new_color = NULL;
2054 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2055 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2057 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2058 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2059 g_free (buffer_format);
2061 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2062 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2063 if (new_color != NULL) {
2064 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2065 (gpointer) new_color);
2068 gtk_widget_destroy (dialog);
2073 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2076 ModestMsgEditWindowPrivate *priv;
2077 GtkWidget *dialog = NULL;
2079 GdkColor *old_color = NULL;
2080 const GdkColor *new_color = NULL;
2082 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2083 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2085 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2086 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2088 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2089 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2090 if (new_color != NULL)
2091 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2093 gtk_widget_destroy (dialog);
2099 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2102 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2103 ModestMsgEditWindowPrivate *priv;
2104 GtkWidget *dialog = NULL;
2106 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2107 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2109 dialog = hildon_color_chooser_new ();
2110 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2111 g_free (buffer_format);
2113 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2115 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2116 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2119 gtk_widget_destroy (dialog);
2124 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2127 ModestMsgEditWindowPrivate *priv;
2128 GtkWidget *dialog = NULL;
2129 GdkColor *old_color = NULL;
2131 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2132 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2134 dialog = hildon_color_chooser_new ();
2135 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2137 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2139 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2140 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2142 gtk_widget_destroy (dialog);
2145 #endif /*!MODEST_HILDON_VERSION_0*/
2150 create_stream_for_uri (const gchar* uri)
2155 TnyStream *result = NULL;
2157 GnomeVFSHandle *handle = NULL;
2158 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2159 if (test == GNOME_VFS_OK) {
2160 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2161 /* Streams over OBEX (Bluetooth) are not seekable but
2162 * we expect them to be (we might need to read them
2163 * several times). So if this is a Bluetooth URI just
2164 * read the whole file into memory (this is not a fast
2165 * protocol so we can assume that these files are not
2166 * going to be very big) */
2167 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2168 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2169 TnyStream *memstream = tny_camel_mem_stream_new ();
2170 tny_stream_write_to_stream (vfssstream, memstream);
2171 g_object_unref (vfssstream);
2174 result = vfssstream;
2182 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2185 ModestMsgEditWindowPrivate *priv;
2186 GtkWidget *dialog = NULL;
2188 GSList *uris = NULL;
2189 GSList *uri_node = NULL;
2191 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2193 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2194 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2195 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2197 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2199 response = gtk_dialog_run (GTK_DIALOG (dialog));
2201 case GTK_RESPONSE_OK:
2202 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2207 gtk_widget_destroy (dialog);
2209 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2211 GnomeVFSHandle *handle = NULL;
2212 GnomeVFSResult result;
2213 GtkTextIter position;
2214 GtkTextMark *insert_mark;
2216 uri = (const gchar *) uri_node->data;
2217 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2218 if (result == GNOME_VFS_OK) {
2220 GnomeVFSFileInfo *info;
2221 gchar *filename, *basename, *escaped_filename;
2222 TnyMimePart *mime_part;
2224 const gchar *mime_type = NULL;
2225 GnomeVFSURI *vfs_uri;
2226 guint64 stream_size;
2228 gnome_vfs_close (handle);
2229 vfs_uri = gnome_vfs_uri_new (uri);
2231 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2232 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2233 g_free (escaped_filename);
2234 gnome_vfs_uri_unref (vfs_uri);
2235 info = gnome_vfs_file_info_new ();
2237 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2238 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2240 mime_type = gnome_vfs_file_info_get_mime_type (info);
2242 mime_part = tny_platform_factory_new_mime_part
2243 (modest_runtime_get_platform_factory ());
2245 TnyStream *stream = create_stream_for_uri (uri);
2247 if (stream == NULL) {
2249 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2251 g_object_unref (mime_part);
2252 gnome_vfs_file_info_unref (info);
2256 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2258 content_id = g_strdup_printf ("%d", priv->next_cid);
2259 tny_mime_part_set_content_id (mime_part, content_id);
2260 g_free (content_id);
2263 basename = g_path_get_basename (filename);
2264 tny_mime_part_set_filename (mime_part, basename);
2267 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2269 if (pixbuf != NULL) {
2270 priv->images_size += stream_size;
2271 priv->images_count ++;
2272 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2273 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2274 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2277 tny_list_prepend (priv->images, (GObject *) mime_part);
2278 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2280 g_object_unref (mime_part);
2281 gnome_vfs_file_info_unref (info);
2290 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2292 GtkWidget *dialog = NULL;
2294 GSList *uris = NULL;
2296 GnomeVFSFileSize total_size, allowed_size;
2297 ModestMsgEditWindowPrivate *priv;
2301 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2303 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2305 if (modest_platform_check_memory_low (MODEST_WINDOW(window)))
2308 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2309 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2310 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2311 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
2313 response = gtk_dialog_run (GTK_DIALOG (dialog));
2315 case GTK_RESPONSE_OK:
2316 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2321 gtk_widget_destroy (dialog);
2323 /* allowed size is the maximum size - what's already there */
2324 modest_attachments_view_get_sizes (
2325 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2326 &att_num, &att_size);
2327 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2330 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2332 const gchar *uri = (const gchar *) uri_node->data;
2334 total_size += modest_msg_edit_window_attach_file_one
2335 (window, uri, allowed_size);
2337 if (total_size > allowed_size) {
2338 g_warning ("%s: total size: %u",
2339 __FUNCTION__, (unsigned int)total_size);
2343 allowed_size -= total_size;
2347 g_slist_foreach (uris, (GFunc) g_free, NULL);
2348 g_slist_free (uris);
2353 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2355 GnomeVFSFileSize allowed_size)
2358 GnomeVFSHandle *handle = NULL;
2359 ModestMsgEditWindowPrivate *priv;
2360 GnomeVFSResult result;
2361 GnomeVFSFileSize size = 0;
2363 g_return_val_if_fail (window, 0);
2364 g_return_val_if_fail (uri, 0);
2366 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2368 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2369 if (result == GNOME_VFS_OK) {
2370 TnyMimePart *mime_part;
2372 const gchar *mime_type = NULL;
2374 gchar *escaped_filename;
2377 GnomeVFSFileInfo *info;
2378 GnomeVFSURI *vfs_uri;
2380 gnome_vfs_close (handle);
2381 vfs_uri = gnome_vfs_uri_new (uri);
2384 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2385 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2386 g_free (escaped_filename);
2387 gnome_vfs_uri_unref (vfs_uri);
2389 info = gnome_vfs_file_info_new ();
2391 if (gnome_vfs_get_file_info (uri,
2393 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2395 mime_type = gnome_vfs_file_info_get_mime_type (info);
2396 mime_part = tny_platform_factory_new_mime_part
2397 (modest_runtime_get_platform_factory ());
2399 /* try to get the attachment's size; this may fail for weird
2400 * file systems, like obex, upnp... */
2401 if (allowed_size != 0 &&
2402 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2404 if (size > allowed_size) {
2405 g_warning ("%s: attachment too big", __FUNCTION__);
2406 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2410 g_warning ("%s: could not get attachment size", __FUNCTION__);
2412 stream = create_stream_for_uri (uri);
2414 if (stream == NULL) {
2416 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2418 g_object_unref (mime_part);
2419 gnome_vfs_file_info_unref (info);
2423 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2424 g_object_unref (stream);
2426 content_id = g_strdup_printf ("%d", priv->next_cid);
2427 tny_mime_part_set_content_id (mime_part, content_id);
2428 g_free (content_id);
2431 basename = g_path_get_basename (filename);
2432 tny_mime_part_set_filename (mime_part, basename);
2435 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2436 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2438 info->size == 0, info->size);
2439 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2440 gtk_widget_show_all (priv->attachments_caption);
2441 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2443 g_object_unref (mime_part);
2444 gnome_vfs_file_info_unref (info);
2451 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2454 ModestMsgEditWindowPrivate *priv;
2457 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2458 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2460 if (att_list == NULL) {
2461 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2463 g_object_ref (att_list);
2466 if (tny_list_get_length (att_list) == 0) {
2467 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2469 GtkWidget *confirmation_dialog = NULL;
2470 gboolean dialog_response;
2471 gchar *message = NULL;
2472 gchar *filename = NULL;
2474 if (tny_list_get_length (att_list) == 1) {
2476 iter = tny_list_create_iterator (att_list);
2477 part = (TnyMimePart *) tny_iterator_get_current (iter);
2478 g_object_unref (iter);
2479 if (TNY_IS_MSG (part)) {
2480 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2482 filename = tny_header_dup_subject (header);
2483 g_object_unref (header);
2485 if (filename == NULL) {
2486 filename = g_strdup (_("mail_va_no_subject"));
2489 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2491 g_object_unref (part);
2493 filename = g_strdup ("");
2495 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2496 tny_list_get_length (att_list)), filename);
2498 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
2500 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
2501 gtk_widget_destroy (confirmation_dialog);
2502 if (!dialog_response) {
2503 g_object_unref (att_list);
2506 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
2508 for (iter = tny_list_create_iterator (att_list);
2509 !tny_iterator_is_done (iter);
2510 tny_iterator_next (iter)) {
2511 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2512 const gchar *att_id;
2513 tny_list_remove (priv->attachments, (GObject *) mime_part);
2515 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2517 if (tny_list_get_length (priv->attachments) == 0)
2518 gtk_widget_hide (priv->attachments_caption);
2519 att_id = tny_mime_part_get_content_id (mime_part);
2521 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2523 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2524 g_object_unref (mime_part);
2526 g_object_unref (iter);
2529 g_object_unref (att_list);
2531 /* if the last attachment has been removed, focus the Subject: field */
2532 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2533 gtk_widget_grab_focus (priv->subject_field);
2537 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2540 ModestMsgEditWindowPrivate *priv;
2541 GdkColor *new_color;
2542 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2544 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2545 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2548 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2550 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2552 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2554 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2559 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2562 ModestMsgEditWindowPrivate *priv;
2563 gint new_size_index;
2564 ModestMsgEditWindow *window;
2567 window = MODEST_MSG_EDIT_WINDOW (userdata);
2568 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2569 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2571 if (gtk_check_menu_item_get_active (menu_item)) {
2573 WPTextBufferFormat format;
2575 memset (&format, 0, sizeof (format));
2576 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2578 label = gtk_bin_get_child (GTK_BIN (menu_item));
2580 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2581 format.cs.font_size = TRUE;
2582 format.cs.text_position = TRUE;
2583 format.cs.font = TRUE;
2584 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2585 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2587 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2588 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2589 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2591 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2592 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2593 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2599 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2602 ModestMsgEditWindowPrivate *priv;
2603 gint new_font_index;
2604 ModestMsgEditWindow *window;
2607 window = MODEST_MSG_EDIT_WINDOW (userdata);
2608 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2609 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2611 if (gtk_check_menu_item_get_active (menu_item)) {
2614 label = gtk_bin_get_child (GTK_BIN (menu_item));
2616 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2618 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2619 GINT_TO_POINTER(new_font_index)))
2620 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2622 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2623 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2624 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2630 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2632 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2633 ModestWindowPrivate *parent_priv;
2634 ModestWindowMgr *mgr;
2635 gboolean is_fullscreen;
2636 GtkAction *fs_toggle_action;
2639 mgr = modest_runtime_get_window_mgr ();
2640 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2642 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2644 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2645 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2646 if (is_fullscreen != active)
2647 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2655 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2658 ModestMsgEditWindowPrivate *priv = NULL;
2659 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2661 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2662 if (!priv->update_caption_visibility)
2665 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2667 gtk_widget_show (priv->cc_caption);
2669 gtk_widget_hide (priv->cc_caption);
2671 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2675 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2678 ModestMsgEditWindowPrivate *priv = NULL;
2679 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2681 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2682 if (!priv->update_caption_visibility)
2685 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2687 gtk_widget_show (priv->bcc_caption);
2689 gtk_widget_hide (priv->bcc_caption);
2691 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2695 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2696 ModestRecptEditor *editor)
2698 ModestMsgEditWindowPrivate *priv;
2700 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2701 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2703 /* we check for low-mem; in that case, show a warning, and don't allow
2704 * for the addressbook
2706 if (modest_platform_check_memory_low (MODEST_WINDOW(window)))
2710 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2712 if (editor == NULL) {
2713 GtkWidget *view_focus;
2714 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2716 /* This code should be kept in sync with ModestRecptEditor. The
2717 textview inside the recpt editor is the one that really gets the
2718 focus. As it's inside a scrolled window, and this one inside the
2719 hbox recpt editor inherits from, we'll need to go up in the
2720 hierarchy to know if the text view is part of the recpt editor
2721 or if it's a different text entry */
2723 if (gtk_widget_get_parent (view_focus)) {
2724 GtkWidget *first_parent;
2726 first_parent = gtk_widget_get_parent (view_focus);
2727 if (gtk_widget_get_parent (first_parent) &&
2728 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2729 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2734 editor = MODEST_RECPT_EDITOR (priv->to_field);
2738 modest_address_book_select_addresses (editor);
2743 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2745 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2747 modest_msg_edit_window_open_addressbook (window, NULL);
2751 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2752 gboolean show_toolbar)
2754 ModestWindowPrivate *parent_priv;
2755 const gchar *action_name;
2758 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2759 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2761 /* We can not just use the code of
2762 modest_msg_edit_window_setup_toolbar because it has a
2763 mixture of both initialization and creation code. */
2765 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2767 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2769 /* Update also the actions (to update the toggles in the
2770 menus), we have to do it manually because some other window
2771 of the same time could have changed it (remember that the
2772 toolbar fullscreen mode is shared by all the windows of the
2774 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2775 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2777 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2779 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2780 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2786 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2787 TnyHeaderFlags priority_flags)
2789 ModestMsgEditWindowPrivate *priv;
2790 ModestWindowPrivate *parent_priv;
2792 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2794 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2795 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2797 if (priv->priority_flags != priority_flags) {
2798 GtkAction *priority_action = NULL;
2800 priv->priority_flags = priority_flags;
2802 switch (priority_flags) {
2803 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2804 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2805 gtk_widget_show (priv->priority_icon);
2806 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2807 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2809 case TNY_HEADER_FLAG_LOW_PRIORITY:
2810 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2811 gtk_widget_show (priv->priority_icon);
2812 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2813 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2816 gtk_widget_hide (priv->priority_icon);
2817 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2818 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2821 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2822 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2827 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2830 ModestMsgEditWindowPrivate *priv;
2831 ModestWindowPrivate *parent_priv;
2832 gint current_format;
2834 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2836 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2837 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2839 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2840 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2842 if (current_format != file_format) {
2843 switch (file_format) {
2844 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2845 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2846 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2848 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2852 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2853 response = gtk_dialog_run (GTK_DIALOG (dialog));
2854 gtk_widget_destroy (dialog);
2855 if (response == GTK_RESPONSE_OK) {
2856 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2858 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2859 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2864 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2865 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2870 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2873 ModestMsgEditWindowPrivate *priv;
2874 WPTextBufferFormat oldfmt, fmt;
2875 gint old_position = 0;
2879 GdkColor *color = NULL;
2880 gboolean bold, bold_set, italic, italic_set;
2881 gboolean underline, underline_set;
2882 gboolean strikethrough, strikethrough_set;
2883 gboolean position_set;
2884 gboolean font_size_set, font_set, color_set;
2887 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2888 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2890 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2891 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2892 GTK_WINDOW(dialog));
2894 /* First we get the currently selected font information */
2895 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2897 switch (oldfmt.text_position) {
2898 case TEXT_POSITION_NORMAL:
2901 case TEXT_POSITION_SUPERSCRIPT:
2909 g_object_set (G_OBJECT (dialog),
2910 "bold", oldfmt.bold != FALSE,
2911 "bold-set", !oldfmt.cs.bold,
2912 "underline", oldfmt.underline != FALSE,
2913 "underline-set", !oldfmt.cs.underline,
2914 "italic", oldfmt.italic != FALSE,
2915 "italic-set", !oldfmt.cs.italic,
2916 "strikethrough", oldfmt.strikethrough != FALSE,
2917 "strikethrough-set", !oldfmt.cs.strikethrough,
2918 "color", &oldfmt.color,
2919 "color-set", !oldfmt.cs.color,
2920 "size", wp_font_size[oldfmt.font_size],
2921 "size-set", !oldfmt.cs.font_size,
2922 "position", old_position,
2923 "position-set", !oldfmt.cs.text_position,
2924 "family", wp_get_font_name (oldfmt.font),
2925 "family-set", !oldfmt.cs.font,
2928 gtk_widget_show_all (dialog);
2929 response = gtk_dialog_run (GTK_DIALOG (dialog));
2930 if (response == GTK_RESPONSE_OK) {
2932 g_object_get( dialog,
2934 "bold-set", &bold_set,
2935 "underline", &underline,
2936 "underline-set", &underline_set,
2938 "italic-set", &italic_set,
2939 "strikethrough", &strikethrough,
2940 "strikethrough-set", &strikethrough_set,
2942 "color-set", &color_set,
2944 "size-set", &font_size_set,
2945 "family", &font_name,
2946 "family-set", &font_set,
2947 "position", &position,
2948 "position-set", &position_set,
2953 if (response == GTK_RESPONSE_OK) {
2954 memset(&fmt, 0, sizeof(fmt));
2960 fmt.italic = italic;
2961 fmt.cs.italic = TRUE;
2963 if (underline_set) {
2964 fmt.underline = underline;
2965 fmt.cs.underline = TRUE;
2967 if (strikethrough_set) {
2968 fmt.strikethrough = strikethrough;
2969 fmt.cs.strikethrough = TRUE;
2974 ? TEXT_POSITION_NORMAL
2975 : ( ( position == 1 )
2976 ? TEXT_POSITION_SUPERSCRIPT
2977 : TEXT_POSITION_SUBSCRIPT );
2978 fmt.cs.text_position = TRUE;
2979 fmt.font_size = oldfmt.font_size;
2983 fmt.cs.color = TRUE;
2986 fmt.font = wp_get_font_index(font_name,
2991 if (font_size_set) {
2992 fmt.cs.font_size = TRUE;
2993 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2995 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2996 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2998 gtk_widget_destroy (dialog);
3000 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3004 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3006 ModestMsgEditWindowPrivate *priv;
3008 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3009 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3011 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3013 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3014 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3019 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3021 ModestMsgEditWindowPrivate *priv;
3023 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3024 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3026 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3028 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3029 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3034 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3036 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3038 priv->can_undo = can_undo;
3042 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3044 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3046 priv->can_redo = can_redo;
3050 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3052 ModestMsgEditWindowPrivate *priv;
3053 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3054 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3056 return priv->can_undo;
3060 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3062 ModestMsgEditWindowPrivate *priv;
3063 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3064 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3066 return priv->can_redo;
3071 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3074 GtkTextIter match_start, match_end;
3076 if (image_id == NULL)
3079 gtk_text_buffer_get_start_iter (buffer, &iter);
3081 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3082 GSList *tags = gtk_text_iter_get_tags (&match_start);
3084 for (node = tags; node != NULL; node = g_slist_next (node)) {
3085 GtkTextTag *tag = (GtkTextTag *) node->data;
3086 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3087 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3088 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3090 offset = gtk_text_iter_get_offset (&match_start);
3091 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3092 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3096 gtk_text_iter_forward_char (&iter);
3101 message_is_empty (ModestMsgEditWindow *window)
3103 ModestMsgEditWindowPrivate *priv = NULL;
3105 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3106 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3108 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3109 * so we can ignore markup.
3111 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3114 count = gtk_text_buffer_get_char_count (buf);
3120 msg_body_focus (GtkWidget *focus,
3121 GdkEventFocus *event,
3125 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3126 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3127 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3132 recpt_field_changed (GtkTextBuffer *buffer,
3133 ModestMsgEditWindow *editor)
3135 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3136 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3140 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3142 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3143 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3147 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3150 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3151 GtkTextBuffer *buffer;
3153 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3154 gtk_text_buffer_set_modified (buffer, modified);
3155 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3156 gtk_text_buffer_set_modified (buffer, modified);
3157 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3158 gtk_text_buffer_set_modified (buffer, modified);
3159 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3163 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3165 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3166 const char *account_name;
3167 GtkTextBuffer *buffer;
3169 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3170 if (gtk_text_buffer_get_modified (buffer))
3172 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3173 if (gtk_text_buffer_get_modified (buffer))
3175 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3176 if (gtk_text_buffer_get_modified (buffer))
3178 if (gtk_text_buffer_get_modified (priv->text_buffer))
3180 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
3181 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3192 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3194 ModestMsgEditWindowPrivate *priv = NULL;
3196 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3197 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3199 /* check if there's no recipient added */
3200 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3201 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3202 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3203 /* no recipient contents, then select contacts */
3204 modest_msg_edit_window_open_addressbook (window, NULL);
3208 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3209 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3212 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3213 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3216 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3217 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3221 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3222 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3223 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3230 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3231 ModestMsgEditWindow *window)
3233 modest_msg_edit_window_offer_attach_file (window);
3237 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3239 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3241 return priv->clipboard_text;
3245 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3247 ModestMsgEditWindow *window)
3249 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3250 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3252 if (!GTK_WIDGET_VISIBLE (window))
3255 g_object_ref (window);
3256 text = gtk_clipboard_wait_for_text (selection_clipboard);
3258 if (priv->clipboard_text != NULL) {
3259 g_free (priv->clipboard_text);
3261 priv->clipboard_text = text;
3263 if (GTK_WIDGET_VISIBLE (window)) {
3264 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3266 g_object_unref (window);
3269 static gboolean clipboard_owner_change_idle (gpointer userdata)
3271 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3272 ModestMsgEditWindowPrivate *priv;
3274 gdk_threads_enter ();
3275 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3276 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3278 priv->clipboard_owner_idle = 0;
3279 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3280 gdk_threads_leave ();
3286 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3288 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3289 if (priv->clipboard_owner_idle == 0) {
3290 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3295 subject_field_move_cursor (GtkEntry *entry,
3296 GtkMovementStep step,
3301 if (!GTK_WIDGET_VISIBLE (window))
3304 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3308 update_window_title (ModestMsgEditWindow *window)
3310 ModestMsgEditWindowPrivate *priv = NULL;
3311 const gchar *subject;
3313 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3314 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3315 if (subject == NULL || subject[0] == '\0')
3316 subject = _("mail_va_new_email");
3318 gtk_window_set_title (GTK_WINDOW (window), subject);
3323 subject_field_changed (GtkEditable *editable,
3324 ModestMsgEditWindow *window)
3326 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3327 update_window_title (window);
3328 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3329 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3330 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3334 subject_field_insert_text (GtkEditable *editable,
3336 gint new_text_length,
3338 ModestMsgEditWindow *window)
3340 GString *result = g_string_new ("");
3342 gint result_len = 0;
3343 const gchar *entry_text = NULL;
3346 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3347 old_length = g_utf8_strlen (entry_text, -1);
3349 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3350 gunichar c = g_utf8_get_char_validated (current, 8);
3351 /* Invalid unichar, stop */
3357 result = g_string_append_unichar (result, c);
3361 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3362 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3365 /* Prevent endless recursion */
3366 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3367 g_signal_emit_by_name (editable, "insert-text",
3368 (gpointer) result->str, (gpointer) result->len,
3369 (gpointer) position, (gpointer) window);
3370 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3374 if (result_len + old_length > 1000) {
3375 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3376 dgettext("hildon-common-strings",
3377 "ckdg_ib_maximum_characters_reached"));
3380 g_string_free (result, TRUE);
3384 text_buffer_insert_text (GtkTextBuffer *buffer,
3387 gint new_text_length,
3388 ModestMsgEditWindow *window)
3390 GString *result = g_string_new ("");
3392 gint result_len = 0;
3393 gboolean changed = FALSE;
3395 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3396 gunichar c = g_utf8_get_char_validated (current, 8);
3397 /* Invalid unichar, stop */
3403 result = g_string_append_c (result, ' ');
3407 result = g_string_append_unichar (result, c);
3413 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3414 g_signal_handlers_block_by_func(G_OBJECT(buffer), G_CALLBACK(text_buffer_insert_text), window);
3415 g_signal_emit_by_name (buffer, "insert-text",
3417 (gpointer) result->str, (gpointer) result->len,
3419 g_signal_handlers_unblock_by_func(G_OBJECT(buffer), G_CALLBACK(text_buffer_insert_text), window);
3422 g_string_free (result, TRUE);
3426 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3429 ModestMsgEditWindowPrivate *priv = NULL;
3431 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3432 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3434 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3437 gtk_widget_show_all (priv->find_toolbar);
3438 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3440 gtk_widget_hide_all (priv->find_toolbar);
3441 gtk_widget_grab_focus (priv->msg_body);
3447 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3449 GtkTextIter *match_start,
3450 GtkTextIter *match_end)
3452 GtkTextIter end_iter;
3453 gchar *str_casefold;
3456 gchar *range_casefold;
3459 gboolean result = FALSE;
3466 gtk_text_iter_forward_to_end (&end_iter);
3468 str_casefold = g_utf8_casefold (str, -1);
3469 str_chars_n = strlen (str);
3471 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3472 range_casefold = g_utf8_casefold (range_text, -1);
3473 range_chars_n = strlen (range_casefold);
3475 if (range_chars_n < str_chars_n) {
3476 g_free (str_casefold);
3477 g_free (range_text);
3478 g_free (range_casefold);
3482 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3483 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3484 if (!g_utf8_collate (range_subtext, str_casefold)) {
3485 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3487 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3488 match_start, match_end, NULL);
3489 g_free (found_text);
3491 g_free (range_subtext);
3495 g_free (str_casefold);
3496 g_free (range_text);
3497 g_free (range_casefold);
3504 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3505 ModestMsgEditWindow *window)
3507 gchar *current_search = NULL;
3508 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3510 GtkTextIter selection_start, selection_end;
3511 GtkTextIter match_start, match_end;
3512 gboolean continue_search = FALSE;
3514 if (message_is_empty (window)) {
3515 g_free (priv->last_search);
3516 priv->last_search = NULL;
3517 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3521 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3522 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3523 g_free (current_search);
3524 g_free (priv->last_search);
3525 priv->last_search = NULL;
3526 /* Information banner about empty search */
3527 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3531 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3532 continue_search = TRUE;
3534 g_free (priv->last_search);
3535 priv->last_search = g_strdup (current_search);
3538 if (continue_search) {
3539 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3540 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3541 &match_start, &match_end);
3543 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3545 GtkTextIter buffer_start;
3546 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3547 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3548 &match_start, &match_end);
3550 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3553 /* Mark as selected the string found in search */
3555 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3556 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3557 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3559 g_free (priv->last_search);
3560 priv->last_search = NULL;
3562 g_free (current_search);
3566 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3567 ModestMsgEditWindow *window)
3569 GtkToggleAction *toggle;
3570 ModestWindowPrivate *parent_priv;
3571 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3573 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3574 gtk_toggle_action_set_active (toggle, FALSE);
3578 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3580 ModestMsgEditWindowPrivate *priv;
3582 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3587 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3590 ModestMsgEditWindowPrivate *priv;
3592 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3598 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3601 ModestMsgEditWindowPrivate *priv;
3602 TnyHeader *header = NULL;
3604 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3605 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3607 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3608 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3610 if (priv->draft_msg != NULL) {
3611 g_object_unref (priv->draft_msg);
3614 if (draft != NULL) {
3615 g_object_ref (draft);
3616 header = tny_msg_get_header (draft);
3617 if (priv->msg_uid) {
3618 g_free (priv->msg_uid);
3619 priv->msg_uid = NULL;
3621 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3622 if (GTK_WIDGET_REALIZED (window))
3623 modest_window_mgr_register_window (mgr, MODEST_WINDOW (window));
3626 priv->draft_msg = draft;
3630 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3631 GtkTextIter *start, GtkTextIter *end,
3634 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3635 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3638 if (tag == NULL+13) return;
3639 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3640 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3641 replace_with_images (window, priv->images);
3646 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3649 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3651 g_return_if_fail (TNY_IS_MIME_PART (part));
3652 tny_list_prepend (priv->attachments, (GObject *) part);
3653 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3654 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3655 gtk_widget_show_all (priv->attachments_caption);
3656 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3660 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3662 ModestMsgEditWindowPrivate *priv;
3664 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3665 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3667 return priv->msg_uid;
3671 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3672 ModestMsgEditWindowWidgetType widget_type)
3674 ModestMsgEditWindowPrivate *priv;
3676 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3677 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3679 switch (widget_type) {
3680 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3681 return priv->msg_body;
3683 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3684 return priv->to_field;
3686 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3687 return priv->cc_field;
3689 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3690 return priv->bcc_field;
3692 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3693 return priv->subject_field;
3695 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3696 return priv->attachments_view;
3704 remove_tags (WPTextBuffer *buffer)
3706 GtkTextIter start, end;
3708 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3709 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3711 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3715 on_account_removed (TnyAccountStore *account_store,
3716 TnyAccount *account,
3719 /* Do nothing if it's a store account, because we use the
3720 transport to send the messages */
3721 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3722 const gchar *parent_acc = NULL;
3723 const gchar *our_acc = NULL;
3725 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3726 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3727 /* Close this window if I'm showing a message of the removed account */
3728 if (strcmp (parent_acc, our_acc) == 0)
3729 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3734 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3736 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3738 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3744 set_zoom_do_nothing (ModestWindow *window,
3750 get_zoom_do_nothing (ModestWindow *window)