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>
41 #include <modest-account-mgr.h>
42 #include <modest-account-mgr-helpers.h>
44 #include <widgets/modest-msg-edit-window.h>
45 #include <widgets/modest-combo-box.h>
46 #include <widgets/modest-recpt-editor.h>
47 #include <widgets/modest-attachments-view.h>
49 #include <modest-runtime.h>
51 #include "modest-platform.h"
52 #include "modest-icon-names.h"
53 #include "modest-widget-memory.h"
54 #include "modest-window-priv.h"
55 #include "modest-mail-operation.h"
56 #include "modest-tny-platform-factory.h"
57 #include "modest-tny-msg.h"
58 #include "modest-tny-folder.h"
59 #include "modest-tny-account.h"
60 #include "modest-address-book.h"
61 #include "modest-text-utils.h"
62 #include <tny-simple-list.h>
63 #include <wptextview.h>
64 #include <wptextbuffer.h>
65 #include "modest-scroll-area.h"
66 #include "modest-msg-edit-window-ui-dimming.h"
68 #include "modest-hildon-includes.h"
69 #ifdef MODEST_HAVE_HILDON0_WIDGETS
70 #include <hildon-widgets/hildon-color-chooser.h>
72 #include "widgets/modest-msg-edit-window-ui.h"
73 #ifdef MODEST_HAVE_HILDON0_WIDGETS
74 #include <libgnomevfs/gnome-vfs-mime-utils.h>
76 #include <libgnomevfs/gnome-vfs-mime.h>
78 #include <modest-utils.h>
79 #include "modest-maemo-utils.h"
82 #define DEFAULT_FONT_SIZE 3
83 #define DEFAULT_FONT 2
84 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
85 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
86 #define DEFAULT_MAIN_VBOX_SPACING 6
87 #define SUBJECT_MAX_LENGTH 1000
88 #define IMAGE_MAX_WIDTH 560
89 #define DEFAULT_FONT_SCALE 1.5
91 static gboolean is_wp_text_buffer_started = FALSE;
93 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
94 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
95 static void modest_msg_edit_window_finalize (GObject *obj);
97 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
98 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
99 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
101 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
102 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
103 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
104 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
105 GtkTextIter *start, GtkTextIter *end,
107 static void text_buffer_insert_text (GtkTextBuffer *buffer,
108 GtkTextIter *location,
111 ModestMsgEditWindow *window);
112 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
113 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
114 static void subject_field_insert_text (GtkEditable *editable,
116 gint new_text_length,
118 ModestMsgEditWindow *window);
119 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
121 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
123 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
125 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
126 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
127 GdkEventWindowState *event,
129 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
130 ModestRecptEditor *editor);
131 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
132 ModestMsgEditWindow *window);
134 /* ModestWindow methods implementation */
135 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
136 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
137 gboolean show_toolbar);
138 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
140 ModestMsgEditWindow *window);
141 static void subject_field_move_cursor (GtkEntry *entry,
142 GtkMovementStep step,
146 static void update_window_title (ModestMsgEditWindow *window);
149 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
150 ModestMsgEditWindow *window);
151 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
152 ModestMsgEditWindow *window);
153 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
155 GtkTextIter *match_start,
156 GtkTextIter *match_end);
158 static void remove_tags (WPTextBuffer *buffer);
160 static void on_account_removed (TnyAccountStore *account_store,
164 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
165 static void set_zoom_do_nothing (ModestWindow *window, gdouble zoom);
166 static gdouble get_zoom_do_nothing (ModestWindow *window);
168 static void init_window (ModestMsgEditWindow *obj);
170 gboolean scroll_drag_timeout (gpointer userdata);
171 static void correct_scroll (ModestMsgEditWindow *w);
172 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w);
173 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
174 ModestMsgEditWindow *userdata);
175 static void text_buffer_mark_set (GtkTextBuffer *buffer,
178 ModestMsgEditWindow *userdata);
179 void vadj_changed (GtkAdjustment *adj,
180 ModestMsgEditWindow *window);
186 static void DEBUG_BUFFER (WPTextBuffer *buffer)
190 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
192 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
193 while (!gtk_text_iter_is_end (&iter)) {
194 GString *output = g_string_new ("");
195 GSList *toggled_tags;
198 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
199 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
200 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
201 GtkTextTag *tag = (GtkTextTag *) node->data;
203 g_object_get (G_OBJECT (tag), "name", &name, NULL);
204 output = g_string_append (output, name);
205 g_string_append (output, " ");
207 output = g_string_append (output, "] OPENED [ ");
208 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
209 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
210 GtkTextTag *tag = (GtkTextTag *) node->data;
212 g_object_get (G_OBJECT (tag), "name", &name, NULL);
213 output = g_string_append (output, name);
214 g_string_append (output, " ");
216 output = g_string_append (output, "]\n");
217 g_message ("%s", output->str);
218 g_string_free (output, TRUE);
219 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
221 g_message ("END BUFFER");
226 /* static gboolean */
227 /* on_key_pressed (GtkWidget *self, */
228 /* GdkEventKey *event, */
229 /* gpointer user_data); */
231 /* list my signals */
238 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
239 struct _ModestMsgEditWindowPrivate {
242 GtkWidget *header_box;
244 ModestPairList *from_field_protos;
245 GtkWidget *from_field;
249 GtkWidget *bcc_field;
250 GtkWidget *subject_field;
251 GtkWidget *attachments_view;
252 GtkWidget *priority_icon;
253 GtkWidget *add_attachment_button;
255 GtkWidget *cc_caption;
256 GtkWidget *bcc_caption;
257 gboolean update_caption_visibility;
258 GtkWidget *attachments_caption;
260 GtkTextBuffer *text_buffer;
262 GtkWidget *font_size_toolitem;
263 GtkWidget *font_face_toolitem;
264 GtkWidget *font_color_button;
265 GSList *font_items_group;
266 GtkWidget *font_tool_button_label;
267 GSList *size_items_group;
268 GtkWidget *size_tool_button_label;
270 GtkWidget *find_toolbar;
274 guint scroll_drag_timeout_id;
278 TnyList *attachments;
283 TnyHeaderFlags priority_flags;
285 gboolean can_undo, can_redo;
286 gulong clipboard_change_handler_id;
287 gulong default_clipboard_change_handler_id;
288 gulong account_removed_handler_id;
289 gchar *clipboard_text;
298 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
299 MODEST_TYPE_MSG_EDIT_WINDOW, \
300 ModestMsgEditWindowPrivate))
302 static GtkWindowClass *parent_class = NULL;
304 /* uncomment the following if you have defined any signals */
305 /* static guint signals[LAST_SIGNAL] = {0}; */
308 modest_msg_edit_window_get_type (void)
310 static GType my_type = 0;
312 static const GTypeInfo my_info = {
313 sizeof(ModestMsgEditWindowClass),
314 NULL, /* base init */
315 NULL, /* base finalize */
316 (GClassInitFunc) modest_msg_edit_window_class_init,
317 NULL, /* class finalize */
318 NULL, /* class data */
319 sizeof(ModestMsgEditWindow),
321 (GInstanceInitFunc) modest_msg_edit_window_init,
324 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
325 "ModestMsgEditWindow",
333 save_state (ModestWindow *self)
335 modest_widget_memory_save (modest_runtime_get_conf(),
336 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
341 restore_settings (ModestMsgEditWindow *self)
343 ModestConf *conf = NULL;
345 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
347 conf = modest_runtime_get_conf ();
348 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
349 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
350 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
351 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL));
352 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
353 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu");
354 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
355 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
357 /* set initial state of cc and bcc */
358 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
359 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
360 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
361 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
362 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
363 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
365 /* Dim at start clipboard actions */
366 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
367 gtk_action_set_sensitive (action, FALSE);
368 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
369 gtk_action_set_sensitive (action, FALSE);
370 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
371 gtk_action_set_sensitive (action, FALSE);
373 modest_widget_memory_restore (conf,
374 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
379 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
381 GObjectClass *gobject_class;
382 ModestWindowClass *modest_window_class;
383 gobject_class = (GObjectClass*) klass;
384 modest_window_class = (ModestWindowClass*) klass;
386 parent_class = g_type_class_peek_parent (klass);
387 gobject_class->finalize = modest_msg_edit_window_finalize;
389 modest_window_class->set_zoom_func = set_zoom_do_nothing;
390 modest_window_class->get_zoom_func = get_zoom_do_nothing;
391 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
392 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
393 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
394 modest_window_class->save_state_func = save_state;
395 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
397 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
401 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
403 ModestMsgEditWindowPrivate *priv;
404 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
406 priv->msg_body = NULL;
408 priv->from_field = NULL;
409 priv->to_field = NULL;
410 priv->cc_field = NULL;
411 priv->bcc_field = NULL;
412 priv->subject_field = NULL;
413 priv->attachments = TNY_LIST (tny_simple_list_new ());
414 priv->images = TNY_LIST (tny_simple_list_new ());
415 priv->images_size = 0;
416 priv->images_count = 0;
419 priv->cc_caption = NULL;
420 priv->bcc_caption = NULL;
421 priv->update_caption_visibility = FALSE;
423 priv->priority_flags = 0;
425 priv->find_toolbar = NULL;
426 priv->last_search = NULL;
428 priv->draft_msg = NULL;
429 priv->outbox_msg = NULL;
430 priv->msg_uid = NULL;
432 priv->can_undo = FALSE;
433 priv->can_redo = FALSE;
434 priv->clipboard_change_handler_id = 0;
435 priv->default_clipboard_change_handler_id = 0;
436 priv->account_removed_handler_id = 0;
437 priv->clipboard_text = NULL;
440 priv->scroll_drag_timeout_id = 0;
441 priv->last_upper = 0.0;
443 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
444 GTK_WINDOW(obj),"applications_email_editor");
446 if (!is_wp_text_buffer_started) {
447 is_wp_text_buffer_started = TRUE;
448 wp_text_buffer_library_init ();
453 hildon_program_add_window (hildon_program_get_instance(),
458 /* FIXME: this is a dup from the one in gtk/ */
461 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
463 static ModestPairList*
464 get_transports (void)
466 GSList *transports = NULL;
468 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
469 GSList *accounts = modest_account_mgr_account_names (account_mgr,
470 TRUE /* only enabled accounts. */);
472 GSList *cursor = accounts;
474 gchar *account_name = cursor->data;
475 gchar *from_string = NULL;
477 from_string = modest_account_mgr_get_from_string (account_mgr,
481 if (from_string && account_name) {
482 gchar *name = account_name;
483 ModestPair *pair = modest_pair_new ((gpointer) name,
484 (gpointer) from_string , TRUE);
485 transports = g_slist_prepend (transports, pair);
488 cursor = cursor->next;
490 g_slist_free (accounts); /* only free the accounts, not the elements,
491 * because they are used in the pairlist */
495 static void window_focus (GtkWindow *window,
499 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
503 scroll_drag_timeout (gpointer userdata)
505 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
506 ModestMsgEditWindowPrivate *priv;
508 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
510 correct_scroll_without_drag_check (win);
512 priv->scroll_drag_timeout_id = 0;
518 correct_scroll_without_drag_check (ModestMsgEditWindow *w)
520 ModestMsgEditWindowPrivate *priv;
523 GdkRectangle rectangle;
529 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
531 if (!gtk_widget_is_focus (priv->msg_body))
534 insert = gtk_text_buffer_get_insert (priv->text_buffer);
535 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
537 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
538 vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll));
539 offset = priv->msg_body->allocation.y;
541 new_value = vadj->value;
543 if ((offset + rectangle.y + rectangle.height) >
544 ((gint) (vadj->value +vadj->page_size))) {
545 new_value = (offset + rectangle.y) + vadj->page_size * 0.75;
546 if (new_value > vadj->upper - vadj->page_size)
547 new_value = vadj->upper - vadj->page_size;
548 } else if ((offset + rectangle.y) < ((gint) vadj->value)) {
549 new_value = (offset + rectangle.y - vadj->page_size * 0.75);
550 if (((gint) (new_value + vadj->page_size)) < (offset + rectangle.y + rectangle.height))
551 new_value = offset + rectangle.y + rectangle.height - (gint) vadj->page_size;
554 if (new_value > vadj->value)
555 new_value = vadj->value;
558 if (vadj->value != new_value) {
559 g_signal_emit_by_name (GTK_TEXT_VIEW(priv->msg_body)->layout,
561 vadj->value = new_value;
562 gtk_adjustment_value_changed (vadj);
563 /* invalidate body */
564 window = gtk_widget_get_parent_window (priv->msg_body);
566 gdk_window_invalidate_rect (window, NULL, TRUE);
572 correct_scroll (ModestMsgEditWindow *w)
574 ModestMsgEditWindowPrivate *priv;
576 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
577 if (gtk_grab_get_current () == priv->msg_body) {
578 if (priv->scroll_drag_timeout_id == 0) {
579 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
585 correct_scroll_without_drag_check (w);
589 text_buffer_end_user_action (GtkTextBuffer *buffer,
590 ModestMsgEditWindow *userdata)
593 correct_scroll (userdata);
597 text_buffer_mark_set (GtkTextBuffer *buffer,
600 ModestMsgEditWindow *userdata)
602 gtk_text_buffer_begin_user_action (buffer);
603 gtk_text_buffer_end_user_action (buffer);
606 void vadj_changed (GtkAdjustment *adj,
607 ModestMsgEditWindow *window)
609 ModestMsgEditWindowPrivate *priv;
611 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
613 if (priv->last_upper != adj->upper) {
614 priv->last_upper = adj->upper;
615 correct_scroll (window);
620 connect_signals (ModestMsgEditWindow *obj)
622 ModestMsgEditWindowPrivate *priv;
624 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
626 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
627 G_CALLBACK (text_buffer_refresh_attributes), obj);
628 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
629 G_CALLBACK (text_buffer_can_undo), obj);
630 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
631 G_CALLBACK (text_buffer_can_redo), obj);
632 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
633 G_CALLBACK (body_changed), obj);
634 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
635 G_CALLBACK (text_buffer_insert_text), obj);
636 g_signal_connect (G_OBJECT (obj), "window-state-event",
637 G_CALLBACK (modest_msg_edit_window_window_state_event),
639 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
640 G_CALLBACK (text_buffer_end_user_action), obj);
641 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
642 G_CALLBACK (text_buffer_mark_set), obj);
643 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
644 G_CALLBACK (text_buffer_apply_tag), obj);
645 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
646 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
647 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
648 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
649 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
650 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
652 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
653 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
655 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
656 G_CALLBACK (msg_body_focus), obj);
657 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
658 G_CALLBACK (msg_body_focus), obj);
659 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
660 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
661 "changed", G_CALLBACK (recpt_field_changed), obj);
662 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
663 "changed", G_CALLBACK (recpt_field_changed), obj);
664 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
665 "changed", G_CALLBACK (recpt_field_changed), obj);
666 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
667 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
668 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
670 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
671 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
673 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
675 G_CALLBACK (vadj_changed),
678 priv->clipboard_change_handler_id =
679 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
680 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
681 priv->default_clipboard_change_handler_id =
682 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
683 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
688 init_window (ModestMsgEditWindow *obj)
690 GtkWidget *from_caption, *to_caption, *subject_caption;
691 GtkWidget *main_vbox;
692 ModestMsgEditWindowPrivate *priv;
693 GtkActionGroup *action_group;
694 ModestWindowPrivate *parent_priv;
695 GdkPixbuf *window_icon = NULL;
696 GError *error = NULL;
698 GtkSizeGroup *size_group;
699 GtkWidget *subject_box;
700 GtkWidget *attachment_icon;
701 GtkWidget *window_box;
702 #if (GTK_MINOR_VERSION >= 10)
703 GdkAtom deserialize_type;
705 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
706 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
708 parent_priv->ui_manager = gtk_ui_manager_new();
709 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
710 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
712 /* Add common actions */
713 gtk_action_group_add_actions (action_group,
714 modest_msg_edit_action_entries,
715 G_N_ELEMENTS (modest_msg_edit_action_entries),
717 gtk_action_group_add_toggle_actions (action_group,
718 modest_msg_edit_toggle_action_entries,
719 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
721 gtk_action_group_add_radio_actions (action_group,
722 modest_msg_edit_alignment_radio_action_entries,
723 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
725 G_CALLBACK (modest_ui_actions_on_change_justify),
727 gtk_action_group_add_radio_actions (action_group,
728 modest_msg_edit_priority_action_entries,
729 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
731 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
733 gtk_action_group_add_radio_actions (action_group,
734 modest_msg_edit_file_format_action_entries,
735 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
736 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
737 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
739 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
740 g_object_unref (action_group);
742 /* Load the UI definition */
743 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
746 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
747 g_clear_error (&error);
750 /* Add accelerators */
751 gtk_window_add_accel_group (GTK_WINDOW (obj),
752 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
754 parent_priv->menubar = NULL;
756 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
758 /* Note: This ModestPairList* must exist for as long as the combo
759 * that uses it, because the ModestComboBox uses the ID opaquely,
760 * so it can't know how to manage its memory. */
761 priv->from_field = modest_combo_box_new (NULL, g_str_equal);
763 priv->to_field = modest_recpt_editor_new ();
764 priv->cc_field = modest_recpt_editor_new ();
765 priv->bcc_field = modest_recpt_editor_new ();
766 subject_box = gtk_hbox_new (FALSE, 0);
767 priv->priority_icon = gtk_image_new ();
768 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
769 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
770 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
771 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
772 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
773 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
774 priv->add_attachment_button = gtk_button_new ();
775 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
776 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
777 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
778 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
779 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
780 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
781 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
782 priv->attachments_view = modest_attachments_view_new (NULL);
784 priv->header_box = gtk_vbox_new (FALSE, 0);
786 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
787 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
788 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
789 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
790 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
791 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
792 g_object_unref (size_group);
794 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
795 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
796 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
797 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
798 gtk_size_group_add_widget (size_group, priv->subject_field);
799 gtk_size_group_add_widget (size_group, priv->attachments_view);
800 g_object_unref (size_group);
802 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
803 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
804 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
805 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
806 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
807 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
808 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
811 priv->msg_body = wp_text_view_new ();
812 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
813 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
814 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
815 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
816 #if (GTK_MINOR_VERSION >= 10)
817 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
818 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
820 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
821 deserialize_type, TRUE);
823 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
825 priv->find_toolbar = hildon_find_toolbar_new (NULL);
826 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
828 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
830 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
831 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
832 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
833 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
835 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
837 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
838 priv->frame = gtk_frame_new (NULL);
839 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
841 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
842 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
843 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
845 window_box = gtk_vbox_new (FALSE, 0);
846 gtk_container_add (GTK_CONTAINER(obj), window_box);
848 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
850 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
852 /* Set window icon */
853 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
855 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
856 g_object_unref (window_icon);
861 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
863 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
865 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
866 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
867 priv->clipboard_change_handler_id))
868 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
869 priv->clipboard_change_handler_id);
870 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
871 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
872 priv->default_clipboard_change_handler_id))
873 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
874 priv->default_clipboard_change_handler_id);
876 if (priv->account_removed_handler_id &&
877 g_signal_handler_is_connected (modest_runtime_get_account_store (),
878 priv->account_removed_handler_id))
879 g_signal_handler_disconnect(modest_runtime_get_account_store (),
880 priv->account_removed_handler_id);
884 modest_msg_edit_window_finalize (GObject *obj)
886 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
888 /* Sanity check: shouldn't be needed, the window mgr should
889 call this function before */
890 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
892 if (priv->clipboard_text != NULL) {
893 g_free (priv->clipboard_text);
894 priv->clipboard_text = NULL;
897 if (priv->draft_msg != NULL) {
898 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
899 if (TNY_IS_HEADER (header)) {
900 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
901 modest_window_mgr_unregister_header (mgr, header);
903 g_object_unref (priv->draft_msg);
904 priv->draft_msg = NULL;
906 if (priv->outbox_msg != NULL) {
907 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
908 if (TNY_IS_HEADER (header)) {
909 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
910 modest_window_mgr_unregister_header (mgr, header);
912 g_object_unref (priv->outbox_msg);
913 priv->outbox_msg = NULL;
915 if (priv->scroll_drag_timeout_id > 0) {
916 g_source_remove (priv->scroll_drag_timeout_id);
917 priv->scroll_drag_timeout_id = 0;
919 g_free (priv->msg_uid);
920 g_free (priv->last_search);
921 g_slist_free (priv->font_items_group);
922 g_slist_free (priv->size_items_group);
923 g_object_unref (priv->attachments);
924 g_object_unref (priv->images);
926 /* This had to stay alive for as long as the combobox that used it: */
927 modest_pair_list_free (priv->from_field_protos);
929 G_OBJECT_CLASS(parent_class)->finalize (obj);
933 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
935 GdkPixbufLoader *loader;
941 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
943 if (loader == NULL) {
949 tny_stream_reset (TNY_STREAM (stream));
950 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
951 unsigned char read_buffer[128];
953 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
955 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
959 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
960 g_object_ref (pixbuf);
961 gdk_pixbuf_loader_close (loader, NULL);
962 g_object_unref (loader);
964 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
965 GdkPixbuf *new_pixbuf;
967 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
968 gdk_pixbuf_get_width (pixbuf);
969 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
970 g_object_unref (pixbuf);
981 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
983 ModestMsgEditWindowPrivate *priv;
986 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
988 for (iter = tny_list_create_iterator (attachments);
989 !tny_iterator_is_done (iter);
990 tny_iterator_next (iter)) {
991 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
992 const gchar *cid = tny_mime_part_get_content_id (part);
993 const gchar *mime_type = tny_mime_part_get_content_type (part);
994 if ((cid != NULL)&&(mime_type != NULL)) {
996 TnyStream *stream = tny_mime_part_get_stream (part);
997 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1000 g_object_unref (stream);
1002 if (pixbuf != NULL) {
1003 priv->images_count ++;
1004 priv->images_size += stream_size;
1005 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1006 g_object_unref (pixbuf);
1009 g_object_unref (part);
1011 g_object_unref (iter);
1015 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1017 TnyMimePart *parent = NULL;
1018 const gchar *content_type = NULL;
1019 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1021 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1023 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1024 parent = g_object_ref (msg);
1025 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1026 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1029 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1030 iter = tny_list_create_iterator (parts);
1031 while (!tny_iterator_is_done (iter)) {
1033 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1034 content_type = tny_mime_part_get_content_type (part);
1035 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1039 g_object_unref (part);
1041 tny_iterator_next (iter);
1043 g_object_unref (iter);
1044 g_object_unref (parts);
1047 if (parent != NULL) {
1048 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1051 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1052 iter = tny_list_create_iterator (parts);
1053 while (!tny_iterator_is_done (iter)) {
1055 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1056 content_type = tny_mime_part_get_content_type (part);
1057 if (content_type && g_str_has_prefix (content_type, "image/")) {
1058 tny_list_prepend (priv->images, (GObject *) part);
1060 g_object_unref (part);
1061 tny_iterator_next (iter);
1063 g_object_unref (iter);
1064 g_object_unref (parts);
1065 g_object_unref (parent);
1070 update_last_cid (ModestMsgEditWindow *self, TnyList *attachments)
1073 ModestMsgEditWindowPrivate *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);
1081 char *invalid = NULL;
1082 gint int_cid = strtol (cid, &invalid, 10);
1083 if ((invalid != NULL) && (*invalid == '\0') && (int_cid > priv->last_cid)) {
1084 priv->last_cid = int_cid;
1087 g_object_unref (part);
1089 g_object_unref (iter);
1093 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1096 const gchar *to, *cc, *bcc, *subject;
1098 ModestMsgEditWindowPrivate *priv;
1100 TnyHeaderFlags priority_flags;
1101 TnyFolder *msg_folder;
1102 gboolean is_html = FALSE;
1104 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1105 g_return_if_fail (TNY_IS_MSG (msg));
1107 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1109 header = tny_msg_get_header (msg);
1110 to = tny_header_get_to (header);
1111 cc = tny_header_get_cc (header);
1112 bcc = tny_header_get_bcc (header);
1113 subject = tny_header_get_subject (header);
1114 priority_flags = tny_header_get_priority (header);
1117 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1119 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1120 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1121 gtk_widget_show (priv->cc_caption);
1122 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1123 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1124 gtk_widget_hide (priv->cc_caption);
1127 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1128 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1129 gtk_widget_show (priv->bcc_caption);
1130 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1131 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1132 gtk_widget_hide (priv->bcc_caption);
1135 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1136 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1139 update_window_title (self);
1141 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1142 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1144 if ((body == NULL)||(body[0] == '\0')) {
1146 body = modest_text_utils_convert_to_html ("");
1149 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1150 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1153 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1156 /* Add attachments to the view */
1157 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1158 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1159 if (tny_list_get_length (priv->attachments) == 0) {
1160 gtk_widget_hide (priv->attachments_caption);
1162 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1163 gtk_widget_show_all (priv->attachments_caption);
1165 get_related_images (self, msg);
1166 update_last_cid (self, priv->attachments);
1167 update_last_cid (self, priv->images);
1168 replace_with_images (self, priv->images);
1170 if (preserve_is_rich && !is_html) {
1171 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1172 /* Get the default format required from configuration */
1173 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1174 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1177 /* Set the default focus depending on having already a To: field or not */
1178 if ((!to)||(*to == '\0')) {
1179 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1181 gtk_widget_grab_focus (priv->msg_body);
1184 /* TODO: lower priority, select in the From: combo to the
1185 value that comes from msg <- not sure, should it be
1188 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1190 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1191 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1193 modest_msg_edit_window_reset_modified (self);
1195 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1196 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1197 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1198 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1200 if (priv->msg_uid) {
1201 g_free (priv->msg_uid);
1202 priv->msg_uid = NULL;
1205 /* we should set a reference to the incoming message if it is a draft */
1206 msg_folder = tny_msg_get_folder (msg);
1208 if (modest_tny_folder_is_local_folder (msg_folder)) {
1209 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1210 if (type == TNY_FOLDER_TYPE_INVALID)
1211 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1213 if (type == TNY_FOLDER_TYPE_DRAFTS)
1214 priv->draft_msg = g_object_ref(msg);
1215 if (type == TNY_FOLDER_TYPE_OUTBOX)
1216 priv->outbox_msg = g_object_ref(msg);
1217 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1219 g_object_unref (msg_folder);
1224 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1227 GList *item_children, *node;
1228 GtkWidget *bin_child;
1230 bin_child = gtk_bin_get_child (GTK_BIN(item));
1232 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1234 for (node = item_children; node != NULL; node = g_list_next (node)) {
1235 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1236 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1239 g_list_free (item_children);
1243 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1246 GList *item_children, *node;
1248 box = gtk_bin_get_child (GTK_BIN (item));
1249 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1250 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1252 for (node = item_children; node != NULL; node = g_list_next (node)) {
1253 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1254 if (GTK_IS_TOGGLE_BUTTON (node->data))
1255 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1256 else if (GTK_IS_BUTTON (node->data))
1257 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1259 g_list_free (item_children);
1264 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1266 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1267 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1268 GtkWidget *placeholder;
1269 GtkWidget *tool_item;
1274 GtkWidget *sizes_menu;
1275 GtkWidget *fonts_menu;
1276 GSList *radio_group = NULL;
1277 GSList *node = NULL;
1281 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1282 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1284 /* Font color placeholder */
1285 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1286 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1289 tool_item = GTK_WIDGET (gtk_tool_item_new ());
1290 priv->font_color_button = hildon_color_button_new ();
1291 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1292 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1293 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
1294 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1295 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1296 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1297 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1299 G_CALLBACK (modest_msg_edit_window_color_button_change),
1302 /* Font size and face placeholder */
1303 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1304 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1306 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1307 priv->size_tool_button_label = gtk_label_new (NULL);
1308 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1309 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1310 size_text,"</span>", NULL);
1311 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1313 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1314 sizes_menu = gtk_menu_new ();
1315 priv->size_items_group = NULL;
1317 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1318 GtkWidget *size_menu_item;
1320 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1321 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1322 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1323 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1324 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1325 gtk_widget_show (size_menu_item);
1327 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1331 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1332 GtkWidget *item = (GtkWidget *) node->data;
1333 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1337 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1338 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1339 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1340 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1341 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1342 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1343 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1344 priv->font_size_toolitem = tool_item;
1347 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1348 priv->font_tool_button_label = gtk_label_new (NULL);
1349 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1350 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1352 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1353 fonts_menu = gtk_menu_new ();
1354 priv->font_items_group = NULL;
1356 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1357 GtkWidget *font_menu_item;
1358 GtkWidget *child_label;
1360 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1361 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1362 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1363 wp_get_font_name (font_index), "</span>", NULL);
1364 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1367 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1368 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1369 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1370 gtk_widget_show (font_menu_item);
1372 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1375 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1376 GtkWidget *item = (GtkWidget *) node->data;
1377 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1380 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1381 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1382 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1383 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1384 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1385 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1386 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1387 priv->font_face_toolitem = tool_item;
1389 /* Set expand and homogeneous for remaining items */
1390 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1391 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1392 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1393 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1394 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1395 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1396 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1397 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1398 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1400 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1401 will not show the tool items added to the placeholders) */
1402 gtk_widget_show_all (parent_priv->toolbar);
1404 /* Set the no show all *after* showing all items. We do not
1405 want the toolbar to be shown with a show all because it
1406 could go agains the gconf setting regarding showing or not
1407 the toolbar of the editor window */
1408 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1414 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1417 ModestWindowPrivate *parent_priv;
1418 ModestMsgEditWindowPrivate *priv;
1419 ModestPair *account_pair = NULL;
1420 ModestDimmingRulesGroup *menu_rules_group = NULL;
1421 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1422 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1423 ModestWindowMgr *mgr = NULL;
1425 g_return_val_if_fail (msg, NULL);
1426 g_return_val_if_fail (account_name, NULL);
1428 mgr = modest_runtime_get_window_mgr ();
1430 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1432 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1433 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1435 /* Menubar. Update the state of some toggles */
1436 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1437 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1438 priv->from_field_protos = get_transports ();
1439 modest_combo_box_set_pair_list (MODEST_COMBO_BOX (priv->from_field), priv->from_field_protos);
1440 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1441 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1444 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1446 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1448 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1450 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
1451 if (account_pair != NULL)
1452 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
1454 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1455 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1456 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1457 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1458 /* Add common dimming rules */
1459 modest_dimming_rules_group_add_rules (menu_rules_group,
1460 modest_msg_edit_window_menu_dimming_entries,
1461 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1462 MODEST_WINDOW (obj));
1463 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1464 modest_msg_edit_window_toolbar_dimming_entries,
1465 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1466 MODEST_WINDOW (obj));
1467 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1468 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1469 MODEST_WINDOW (obj));
1470 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1471 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1472 MODEST_WINDOW (obj));
1473 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1474 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1475 MODEST_WINDOW (obj));
1476 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1477 modest_msg_edit_window_clipboard_dimming_entries,
1478 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1479 MODEST_WINDOW (obj));
1480 /* Insert dimming rules group for this window */
1481 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1482 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1483 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1484 /* Checks the dimming rules */
1485 g_object_unref (menu_rules_group);
1486 g_object_unref (toolbar_rules_group);
1487 g_object_unref (clipboard_rules_group);
1488 gtk_widget_show_all (GTK_WIDGET (obj));
1489 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, MODEST_MSG_EDIT_WINDOW (obj));
1491 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1493 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1495 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1496 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1497 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1498 priv->update_caption_visibility = TRUE;
1500 modest_msg_edit_window_reset_modified (MODEST_MSG_EDIT_WINDOW (obj));
1502 /* Track account-removed signal, this window should be closed
1503 in the case we're creating a mail associated to the account
1505 priv->account_removed_handler_id =
1506 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1508 G_CALLBACK(on_account_removed),
1511 return (ModestWindow*) obj;
1515 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1517 GString **string_buffer = (GString **) user_data;
1519 *string_buffer = g_string_append (*string_buffer, buffer);
1525 * @result: A new string which should be freed with g_free().
1528 get_formatted_data (ModestMsgEditWindow *edit_window)
1530 ModestMsgEditWindowPrivate *priv;
1531 GString *string_buffer = g_string_new ("");
1533 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1535 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1537 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1539 return g_string_free (string_buffer, FALSE);
1544 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1547 const gchar *account_name;
1548 ModestMsgEditWindowPrivate *priv;
1549 TnyIterator *att_iter;
1551 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1553 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1555 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1556 g_return_val_if_fail (account_name, NULL);
1559 /* don't free these (except from) */
1560 data = g_slice_new0 (MsgData);
1561 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1563 data->account_name = g_strdup (account_name);
1564 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1565 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1566 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1567 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1568 if (priv->draft_msg) {
1569 data->draft_msg = g_object_ref (priv->draft_msg);
1570 } else if (priv->outbox_msg) {
1571 data->draft_msg = g_object_ref (priv->outbox_msg);
1573 data->draft_msg = NULL;
1576 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1578 gtk_text_buffer_get_bounds (buf, &b, &e);
1579 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1581 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1582 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1584 data->html_body = NULL;
1586 /* deep-copy the data */
1587 att_iter = tny_list_create_iterator (priv->attachments);
1588 data->attachments = NULL;
1589 while (!tny_iterator_is_done (att_iter)) {
1590 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1591 if (!(TNY_IS_MIME_PART(part))) {
1592 g_warning ("strange data in attachment list");
1593 g_object_unref (part);
1594 tny_iterator_next (att_iter);
1597 data->attachments = g_list_append (data->attachments,
1599 tny_iterator_next (att_iter);
1601 g_object_unref (att_iter);
1603 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1604 att_iter = tny_list_create_iterator (priv->images);
1605 data->images = NULL;
1606 while (!tny_iterator_is_done (att_iter)) {
1607 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1609 if (!(TNY_IS_MIME_PART(part))) {
1610 g_warning ("strange data in attachment list");
1611 g_object_unref (part);
1612 tny_iterator_next (att_iter);
1615 cid = tny_mime_part_get_content_id (part);
1617 gchar *image_tag_id;
1618 GtkTextTag *image_tag;
1620 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1621 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1622 g_free (image_tag_id);
1624 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1626 ((gtk_text_iter_has_tag (&iter, image_tag))||
1627 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1628 data->images = g_list_append (data->images,
1629 g_object_ref (part));
1631 g_object_unref (part);
1632 tny_iterator_next (att_iter);
1634 g_object_unref (att_iter);
1636 data->priority_flags = priv->priority_flags;
1643 unref_gobject (GObject *obj, gpointer data)
1645 if (!G_IS_OBJECT(obj))
1647 g_object_unref (obj);
1651 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1654 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1662 g_free (data->from);
1663 g_free (data->subject);
1664 g_free (data->plain_body);
1665 g_free (data->html_body);
1666 g_free (data->account_name);
1668 if (data->draft_msg != NULL) {
1669 g_object_unref (data->draft_msg);
1670 data->draft_msg = NULL;
1673 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1674 g_list_free (data->attachments);
1675 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1676 g_list_free (data->images);
1678 g_slice_free (MsgData, data);
1682 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1684 guint64 *parts_size)
1686 ModestMsgEditWindowPrivate *priv;
1688 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1690 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1692 /* TODO: add images */
1693 *parts_size += priv->images_size;
1694 *parts_count += priv->images_count;
1699 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1702 ModestMsgEditWindowPrivate *priv = NULL;
1703 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1705 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1707 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1709 return MODEST_MSG_EDIT_FORMAT_HTML;
1711 return MODEST_MSG_EDIT_FORMAT_TEXT;
1715 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1716 ModestMsgEditFormat format)
1718 ModestMsgEditWindowPrivate *priv;
1720 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1721 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1724 case MODEST_MSG_EDIT_FORMAT_HTML:
1725 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1727 case MODEST_MSG_EDIT_FORMAT_TEXT:
1728 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1731 g_return_if_reached ();
1735 ModestMsgEditFormatState *
1736 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1738 ModestMsgEditFormatState *format_state = NULL;
1739 ModestMsgEditWindowPrivate *priv;
1740 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1742 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1743 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1745 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1747 format_state = g_new0 (ModestMsgEditFormatState, 1);
1748 format_state->bold = buffer_format->bold&0x1;
1749 format_state->italics = buffer_format->italic&0x1;
1750 format_state->bullet = buffer_format->bullet&0x1;
1751 format_state->color = buffer_format->color;
1752 format_state->font_size = buffer_format->font_size;
1753 format_state->font_family = wp_get_font_name (buffer_format->font);
1754 format_state->justification = buffer_format->justification;
1755 g_free (buffer_format);
1757 return format_state;
1762 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1763 const ModestMsgEditFormatState *format_state)
1765 ModestMsgEditWindowPrivate *priv;
1766 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1767 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1768 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1769 g_return_if_fail (format_state != NULL);
1771 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1772 gtk_widget_grab_focus (priv->msg_body);
1773 buffer_format->bold = (format_state->bold != FALSE);
1774 buffer_format->italic = (format_state->italics != FALSE);
1775 buffer_format->color = format_state->color;
1776 buffer_format->font_size = format_state->font_size;
1777 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1778 buffer_format->justification = format_state->justification;
1779 buffer_format->bullet = format_state->bullet;
1781 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1783 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1784 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1785 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1786 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1787 buffer_format->cs.font = (buffer_format->font != current_format->font);
1788 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1789 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1791 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1792 if (buffer_format->cs.bold) {
1793 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1794 GINT_TO_POINTER (buffer_format->bold&0x1));
1796 if (buffer_format->cs.italic) {
1797 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1798 GINT_TO_POINTER (buffer_format->italic&0x1));
1800 if (buffer_format->cs.color) {
1801 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1802 GINT_TO_POINTER (&(buffer_format->color)));
1804 if (buffer_format->cs.font_size) {
1805 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1806 GINT_TO_POINTER (buffer_format->font_size));
1808 if (buffer_format->cs.justification) {
1809 switch (buffer_format->justification) {
1810 case GTK_JUSTIFY_LEFT:
1811 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1812 GINT_TO_POINTER(TRUE));
1814 case GTK_JUSTIFY_CENTER:
1815 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1816 GINT_TO_POINTER(TRUE));
1818 case GTK_JUSTIFY_RIGHT:
1819 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1820 GINT_TO_POINTER(TRUE));
1827 if (buffer_format->cs.font) {
1828 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1829 GINT_TO_POINTER (buffer_format->font));
1831 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1832 if (buffer_format->cs.bullet) {
1833 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1834 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1836 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1838 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1840 g_free (current_format);
1845 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1847 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1849 ModestWindowPrivate *parent_priv;
1850 ModestMsgEditWindowPrivate *priv;
1851 GtkWidget *new_size_menuitem;
1852 GtkWidget *new_font_menuitem;
1854 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1855 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1857 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1858 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1859 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1860 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1862 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1863 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1864 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1867 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1869 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1870 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1872 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1873 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1875 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1876 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1879 switch (buffer_format->justification)
1881 case GTK_JUSTIFY_LEFT:
1882 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentLeftMenu");
1884 case GTK_JUSTIFY_CENTER:
1885 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentCenterMenu");
1887 case GTK_JUSTIFY_RIGHT:
1888 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentRightMenu");
1895 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1897 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1898 G_CALLBACK (modest_msg_edit_window_color_button_change),
1900 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1901 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1902 G_CALLBACK (modest_msg_edit_window_color_button_change),
1905 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1906 buffer_format->font_size))->data);
1907 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1911 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1912 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1913 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1915 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1916 G_CALLBACK (modest_msg_edit_window_size_change),
1918 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1919 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1920 G_CALLBACK (modest_msg_edit_window_size_change),
1924 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1925 buffer_format->font))->data);
1926 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1930 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1931 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1932 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1934 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1935 G_CALLBACK (modest_msg_edit_window_font_change),
1937 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1938 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1939 G_CALLBACK (modest_msg_edit_window_font_change),
1943 g_free (buffer_format);
1947 #ifdef MODEST_HILDON_VERSION_0
1949 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1952 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1953 ModestMsgEditWindowPrivate *priv;
1954 GtkWidget *dialog = NULL;
1956 GdkColor *new_color = NULL;
1958 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1959 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1961 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1962 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1963 g_free (buffer_format);
1965 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
1966 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1967 if (new_color != NULL) {
1968 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1969 (gpointer) new_color);
1972 gtk_widget_destroy (dialog);
1977 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1980 ModestMsgEditWindowPrivate *priv;
1981 GtkWidget *dialog = NULL;
1983 GdkColor *old_color = NULL;
1984 const GdkColor *new_color = NULL;
1986 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1987 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1989 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1990 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1992 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
1993 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1994 if (new_color != NULL)
1995 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1997 gtk_widget_destroy (dialog);
2003 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2006 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2007 ModestMsgEditWindowPrivate *priv;
2008 GtkWidget *dialog = NULL;
2010 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2011 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2013 dialog = hildon_color_chooser_new ();
2014 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2015 g_free (buffer_format);
2017 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2019 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2020 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2023 gtk_widget_destroy (dialog);
2028 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2031 ModestMsgEditWindowPrivate *priv;
2032 GtkWidget *dialog = NULL;
2033 GdkColor *old_color = NULL;
2035 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2036 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2038 dialog = hildon_color_chooser_new ();
2039 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2041 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2043 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2044 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2046 gtk_widget_destroy (dialog);
2049 #endif /*!MODEST_HILDON_VERSION_0*/
2053 static TnyStream* create_stream_for_uri (const gchar* uri)
2058 TnyStream *result = NULL;
2060 GnomeVFSHandle *handle = NULL;
2061 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2062 if (test == GNOME_VFS_OK) {
2063 /* Create the tinymail stream: */
2064 /* Presumably tinymai will call gnome_vfs_close (handle) later. */
2065 result = TNY_STREAM (tny_vfs_stream_new (handle));
2072 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2075 ModestMsgEditWindowPrivate *priv;
2076 GtkWidget *dialog = NULL;
2078 GSList *uris = NULL;
2079 GSList *uri_node = NULL;
2081 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2083 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2084 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2085 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2087 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2089 response = gtk_dialog_run (GTK_DIALOG (dialog));
2091 case GTK_RESPONSE_OK:
2092 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2097 gtk_widget_destroy (dialog);
2099 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2101 GnomeVFSHandle *handle = NULL;
2102 GnomeVFSResult result;
2103 GtkTextIter position;
2104 GtkTextMark *insert_mark;
2106 uri = (const gchar *) uri_node->data;
2107 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2108 if (result == GNOME_VFS_OK) {
2110 GnomeVFSFileInfo *info;
2111 gchar *filename, *basename, *escaped_filename;
2112 TnyMimePart *mime_part;
2114 const gchar *mime_type = NULL;
2115 GnomeVFSURI *vfs_uri;
2116 guint64 stream_size;
2118 vfs_uri = gnome_vfs_uri_new (uri);
2120 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2121 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2122 g_free (escaped_filename);
2123 gnome_vfs_uri_unref (vfs_uri);
2124 info = gnome_vfs_file_info_new ();
2126 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2127 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2129 mime_type = gnome_vfs_file_info_get_mime_type (info);
2131 mime_part = tny_platform_factory_new_mime_part
2132 (modest_runtime_get_platform_factory ());
2134 TnyStream *stream = create_stream_for_uri (uri);
2135 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2137 content_id = g_strdup_printf ("%d", priv->last_cid);
2138 tny_mime_part_set_content_id (mime_part, content_id);
2139 g_free (content_id);
2142 basename = g_path_get_basename (filename);
2143 tny_mime_part_set_filename (mime_part, basename);
2146 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2148 if (pixbuf != NULL) {
2149 priv->images_size += stream_size;
2150 priv->images_count ++;
2151 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2152 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2153 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2156 tny_list_prepend (priv->images, (GObject *) mime_part);
2157 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2159 g_object_unref (mime_part);
2160 gnome_vfs_file_info_unref (info);
2169 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2171 GtkWidget *dialog = NULL;
2173 GSList *uris = NULL;
2176 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2177 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2178 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2180 response = gtk_dialog_run (GTK_DIALOG (dialog));
2182 case GTK_RESPONSE_OK:
2183 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2188 gtk_widget_destroy (dialog);
2190 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2191 const gchar *uri = (const gchar *) uri_node->data;
2192 modest_msg_edit_window_attach_file_one (window, uri);
2194 g_slist_foreach (uris, (GFunc) g_free, NULL);
2195 g_slist_free (uris);
2199 modest_msg_edit_window_attach_file_one (
2200 ModestMsgEditWindow *window,
2203 GnomeVFSHandle *handle = NULL;
2204 ModestMsgEditWindowPrivate *priv;
2205 GnomeVFSResult result;
2207 g_return_if_fail (window);
2208 g_return_if_fail (uri);
2210 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2212 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2213 if (result == GNOME_VFS_OK) {
2214 TnyMimePart *mime_part;
2216 const gchar *mime_type = NULL;
2218 gchar *escaped_filename;
2221 GnomeVFSFileInfo *info;
2222 GnomeVFSURI *vfs_uri;
2224 vfs_uri = gnome_vfs_uri_new (uri);
2227 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2228 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2229 g_free (escaped_filename);
2230 gnome_vfs_uri_unref (vfs_uri);
2232 info = gnome_vfs_file_info_new ();
2234 if (gnome_vfs_get_file_info (uri,
2236 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2238 mime_type = gnome_vfs_file_info_get_mime_type (info);
2239 mime_part = tny_platform_factory_new_mime_part
2240 (modest_runtime_get_platform_factory ());
2241 stream = TNY_STREAM (tny_vfs_stream_new (handle));
2243 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2245 g_object_unref (stream);
2247 content_id = g_strdup_printf ("%d", priv->last_cid);
2248 tny_mime_part_set_content_id (mime_part, content_id);
2249 g_free (content_id);
2252 basename = g_path_get_basename (filename);
2253 tny_mime_part_set_filename (mime_part, basename);
2256 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2257 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2259 info->size == 0, info->size);
2260 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2261 gtk_widget_show_all (priv->attachments_caption);
2262 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2264 g_object_unref (mime_part);
2265 gnome_vfs_file_info_unref (info);
2270 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2273 ModestMsgEditWindowPrivate *priv;
2276 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2277 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2279 if (att_list == NULL) {
2280 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2282 g_object_ref (att_list);
2285 if (tny_list_get_length (att_list) == 0) {
2286 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2288 GtkWidget *confirmation_dialog = NULL;
2289 gboolean dialog_response;
2290 gchar *message = NULL;
2291 gchar *filename = NULL;
2293 if (tny_list_get_length (att_list) == 1) {
2295 iter = tny_list_create_iterator (att_list);
2296 part = (TnyMimePart *) tny_iterator_get_current (iter);
2297 g_object_unref (iter);
2298 if (TNY_IS_MSG (part)) {
2299 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2301 filename = g_strdup (tny_header_get_subject (header));
2302 g_object_unref (header);
2304 if (filename == NULL) {
2305 filename = g_strdup (_("mail_va_no_subject"));
2308 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2310 g_object_unref (part);
2312 filename = g_strdup ("");
2314 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2315 (tny_list_get_length (att_list) == 1)), filename);
2317 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
2319 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
2320 gtk_widget_destroy (confirmation_dialog);
2321 if (!dialog_response) {
2322 g_object_unref (att_list);
2325 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
2327 for (iter = tny_list_create_iterator (att_list);
2328 !tny_iterator_is_done (iter);
2329 tny_iterator_next (iter)) {
2330 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2331 const gchar *att_id;
2332 tny_list_remove (priv->attachments, (GObject *) mime_part);
2334 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2336 if (tny_list_get_length (priv->attachments) == 0)
2337 gtk_widget_hide (priv->attachments_caption);
2338 att_id = tny_mime_part_get_content_id (mime_part);
2340 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2342 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2343 g_object_unref (mime_part);
2345 g_object_unref (iter);
2348 g_object_unref (att_list);
2350 /* if the last attachment has been removed, focus the Subject: field */
2351 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2352 gtk_widget_grab_focus (priv->subject_field);
2356 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2359 ModestMsgEditWindowPrivate *priv;
2360 GdkColor *new_color;
2361 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2363 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2364 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2367 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2369 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2371 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2373 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2378 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2381 ModestMsgEditWindowPrivate *priv;
2382 gint new_size_index;
2383 ModestMsgEditWindow *window;
2386 window = MODEST_MSG_EDIT_WINDOW (userdata);
2387 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2388 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2390 if (gtk_check_menu_item_get_active (menu_item)) {
2392 WPTextBufferFormat format;
2394 memset (&format, 0, sizeof (format));
2395 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2397 label = gtk_bin_get_child (GTK_BIN (menu_item));
2399 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2400 format.cs.font_size = TRUE;
2401 format.cs.text_position = TRUE;
2402 format.cs.font = TRUE;
2403 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2404 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2406 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2407 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2408 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2410 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2411 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2412 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2418 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2421 ModestMsgEditWindowPrivate *priv;
2422 gint new_font_index;
2423 ModestMsgEditWindow *window;
2426 window = MODEST_MSG_EDIT_WINDOW (userdata);
2427 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2428 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2430 if (gtk_check_menu_item_get_active (menu_item)) {
2433 label = gtk_bin_get_child (GTK_BIN (menu_item));
2435 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2437 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2438 GINT_TO_POINTER(new_font_index)))
2439 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2441 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2442 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2443 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2449 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2451 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2452 ModestWindowPrivate *parent_priv;
2453 ModestWindowMgr *mgr;
2454 gboolean is_fullscreen;
2455 GtkAction *fs_toggle_action;
2458 mgr = modest_runtime_get_window_mgr ();
2459 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2461 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2463 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2464 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2465 if (is_fullscreen != active)
2466 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2474 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2477 ModestMsgEditWindowPrivate *priv = NULL;
2478 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2480 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2481 if (!priv->update_caption_visibility)
2484 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2486 gtk_widget_show (priv->cc_caption);
2488 gtk_widget_hide (priv->cc_caption);
2490 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2494 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2497 ModestMsgEditWindowPrivate *priv = NULL;
2498 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2500 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2501 if (!priv->update_caption_visibility)
2504 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2506 gtk_widget_show (priv->bcc_caption);
2508 gtk_widget_hide (priv->bcc_caption);
2510 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2514 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2515 ModestRecptEditor *editor)
2517 ModestMsgEditWindowPrivate *priv;
2519 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2520 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2521 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2523 if (editor == NULL) {
2524 GtkWidget *view_focus;
2525 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2527 /* This code should be kept in sync with ModestRecptEditor. The
2528 textview inside the recpt editor is the one that really gets the
2529 focus. As it's inside a scrolled window, and this one inside the
2530 hbox recpt editor inherits from, we'll need to go up in the
2531 hierarchy to know if the text view is part of the recpt editor
2532 or if it's a different text entry */
2534 if (gtk_widget_get_parent (view_focus)) {
2535 GtkWidget *first_parent;
2537 first_parent = gtk_widget_get_parent (view_focus);
2538 if (gtk_widget_get_parent (first_parent) &&
2539 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2540 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2545 editor = MODEST_RECPT_EDITOR (priv->to_field);
2549 modest_address_book_select_addresses (editor);
2554 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2556 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2558 modest_msg_edit_window_open_addressbook (window, NULL);
2562 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2563 gboolean show_toolbar)
2565 ModestWindowPrivate *parent_priv;
2566 const gchar *action_name;
2569 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2570 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2572 /* We can not just use the code of
2573 modest_msg_edit_window_setup_toolbar because it has a
2574 mixture of both initialization and creation code. */
2576 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2578 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2580 /* Update also the actions (to update the toggles in the
2581 menus), we have to do it manually because some other window
2582 of the same time could have changed it (remember that the
2583 toolbar fullscreen mode is shared by all the windows of the
2585 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2586 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2588 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2590 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2591 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2597 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2598 TnyHeaderFlags priority_flags)
2600 ModestMsgEditWindowPrivate *priv;
2601 ModestWindowPrivate *parent_priv;
2603 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2605 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2606 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2608 if (priv->priority_flags != priority_flags) {
2609 GtkAction *priority_action = NULL;
2611 priv->priority_flags = priority_flags;
2613 switch (priority_flags) {
2614 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2615 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2616 gtk_widget_show (priv->priority_icon);
2617 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2618 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2620 case TNY_HEADER_FLAG_LOW_PRIORITY:
2621 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2622 gtk_widget_show (priv->priority_icon);
2623 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2624 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2627 gtk_widget_hide (priv->priority_icon);
2628 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2629 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2632 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2633 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2638 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2641 ModestMsgEditWindowPrivate *priv;
2642 ModestWindowPrivate *parent_priv;
2643 gint current_format;
2645 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2647 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2648 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2650 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2651 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2653 if (current_format != file_format) {
2654 switch (file_format) {
2655 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2656 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2657 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2659 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2663 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2664 response = gtk_dialog_run (GTK_DIALOG (dialog));
2665 gtk_widget_destroy (dialog);
2666 if (response == GTK_RESPONSE_OK) {
2667 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2669 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2670 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2675 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2680 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2683 ModestMsgEditWindowPrivate *priv;
2684 WPTextBufferFormat oldfmt, fmt;
2685 gint old_position = 0;
2689 GdkColor *color = NULL;
2690 gboolean bold, bold_set, italic, italic_set;
2691 gboolean underline, underline_set;
2692 gboolean strikethrough, strikethrough_set;
2693 gboolean position_set;
2694 gboolean font_size_set, font_set, color_set;
2697 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2698 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2700 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2702 /* First we get the currently selected font information */
2703 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2705 switch (oldfmt.text_position) {
2706 case TEXT_POSITION_NORMAL:
2709 case TEXT_POSITION_SUPERSCRIPT:
2717 g_object_set (G_OBJECT (dialog),
2718 "bold", oldfmt.bold != FALSE,
2719 "bold-set", !oldfmt.cs.bold,
2720 "underline", oldfmt.underline != FALSE,
2721 "underline-set", !oldfmt.cs.underline,
2722 "italic", oldfmt.italic != FALSE,
2723 "italic-set", !oldfmt.cs.italic,
2724 "strikethrough", oldfmt.strikethrough != FALSE,
2725 "strikethrough-set", !oldfmt.cs.strikethrough,
2726 "color", &oldfmt.color,
2727 "color-set", !oldfmt.cs.color,
2728 "size", wp_font_size[oldfmt.font_size],
2729 "size-set", !oldfmt.cs.font_size,
2730 "position", old_position,
2731 "position-set", !oldfmt.cs.text_position,
2732 "family", wp_get_font_name (oldfmt.font),
2733 "family-set", !oldfmt.cs.font,
2736 gtk_widget_show_all (dialog);
2737 response = gtk_dialog_run (GTK_DIALOG (dialog));
2738 if (response == GTK_RESPONSE_OK) {
2740 g_object_get( dialog,
2742 "bold-set", &bold_set,
2743 "underline", &underline,
2744 "underline-set", &underline_set,
2746 "italic-set", &italic_set,
2747 "strikethrough", &strikethrough,
2748 "strikethrough-set", &strikethrough_set,
2750 "color-set", &color_set,
2752 "size-set", &font_size_set,
2753 "family", &font_name,
2754 "family-set", &font_set,
2755 "position", &position,
2756 "position-set", &position_set,
2761 if (response == GTK_RESPONSE_OK) {
2762 memset(&fmt, 0, sizeof(fmt));
2768 fmt.italic = italic;
2769 fmt.cs.italic = TRUE;
2771 if (underline_set) {
2772 fmt.underline = underline;
2773 fmt.cs.underline = TRUE;
2775 if (strikethrough_set) {
2776 fmt.strikethrough = strikethrough;
2777 fmt.cs.strikethrough = TRUE;
2782 ? TEXT_POSITION_NORMAL
2783 : ( ( position == 1 )
2784 ? TEXT_POSITION_SUPERSCRIPT
2785 : TEXT_POSITION_SUBSCRIPT );
2786 fmt.cs.text_position = TRUE;
2787 fmt.font_size = oldfmt.font_size;
2791 fmt.cs.color = TRUE;
2794 fmt.font = wp_get_font_index(font_name,
2799 if (font_size_set) {
2800 fmt.cs.font_size = TRUE;
2801 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2803 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2804 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2806 gtk_widget_destroy (dialog);
2808 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2812 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2814 ModestMsgEditWindowPrivate *priv;
2816 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2817 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2819 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2821 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2822 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2827 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2829 ModestMsgEditWindowPrivate *priv;
2831 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2832 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2834 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2836 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2837 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2842 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2844 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2846 priv->can_undo = can_undo;
2850 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2852 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2854 priv->can_redo = can_redo;
2858 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2860 ModestMsgEditWindowPrivate *priv;
2861 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2862 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2864 return priv->can_undo;
2868 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2870 ModestMsgEditWindowPrivate *priv;
2871 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2872 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2874 return priv->can_redo;
2879 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2882 GtkTextIter match_start, match_end;
2884 if (image_id == NULL)
2887 gtk_text_buffer_get_start_iter (buffer, &iter);
2889 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2890 GSList *tags = gtk_text_iter_get_tags (&match_start);
2892 for (node = tags; node != NULL; node = g_slist_next (node)) {
2893 GtkTextTag *tag = (GtkTextTag *) node->data;
2894 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2895 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2896 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2898 offset = gtk_text_iter_get_offset (&match_start);
2899 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2900 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2904 gtk_text_iter_forward_char (&iter);
2909 message_is_empty (ModestMsgEditWindow *window)
2911 ModestMsgEditWindowPrivate *priv = NULL;
2913 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2914 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2916 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
2917 * so we can ignore markup.
2919 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
2922 count = gtk_text_buffer_get_char_count (buf);
2928 msg_body_focus (GtkWidget *focus,
2929 GdkEventFocus *event,
2933 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
2934 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
2935 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
2940 recpt_field_changed (GtkTextBuffer *buffer,
2941 ModestMsgEditWindow *editor)
2943 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
2944 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
2948 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
2950 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
2951 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
2955 modest_msg_edit_window_reset_modified (ModestMsgEditWindow *editor)
2957 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2958 GtkTextBuffer *buffer;
2960 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2961 gtk_text_buffer_set_modified (buffer, FALSE);
2962 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2963 gtk_text_buffer_set_modified (buffer, FALSE);
2964 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2965 gtk_text_buffer_set_modified (buffer, FALSE);
2966 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2970 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2972 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2973 GtkTextBuffer *buffer;
2975 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2976 if (gtk_text_buffer_get_modified (buffer))
2978 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2979 if (gtk_text_buffer_get_modified (buffer))
2981 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2982 if (gtk_text_buffer_get_modified (buffer))
2984 if (gtk_text_buffer_get_modified (priv->text_buffer))
2994 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
2996 ModestMsgEditWindowPrivate *priv = NULL;
2998 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2999 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3001 /* check if there's no recipient added */
3002 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3003 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3004 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3005 /* no recipient contents, then select contacts */
3006 modest_msg_edit_window_open_addressbook (window, NULL);
3010 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3011 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3014 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3015 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3018 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3019 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3023 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3024 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3025 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3032 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3033 ModestMsgEditWindow *window)
3035 modest_msg_edit_window_offer_attach_file (window);
3039 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3041 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3043 return priv->clipboard_text;
3047 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3049 ModestMsgEditWindow *window)
3051 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3052 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3054 if (!GTK_WIDGET_VISIBLE (window))
3057 text = gtk_clipboard_wait_for_text (selection_clipboard);
3059 if (priv->clipboard_text != NULL) {
3060 g_free (priv->clipboard_text);
3062 priv->clipboard_text = text;
3064 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3067 subject_field_move_cursor (GtkEntry *entry,
3068 GtkMovementStep step,
3073 if (!GTK_WIDGET_VISIBLE (window))
3076 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3080 update_window_title (ModestMsgEditWindow *window)
3082 ModestMsgEditWindowPrivate *priv = NULL;
3083 const gchar *subject;
3085 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3086 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3087 if (subject == NULL || subject[0] == '\0')
3088 subject = _("mail_va_new_email");
3090 gtk_window_set_title (GTK_WINDOW (window), subject);
3095 subject_field_changed (GtkEditable *editable,
3096 ModestMsgEditWindow *window)
3098 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3099 update_window_title (window);
3100 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3101 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3102 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3106 subject_field_insert_text (GtkEditable *editable,
3108 gint new_text_length,
3110 ModestMsgEditWindow *window)
3112 GString *result = g_string_new ("");
3114 gint result_len = 0;
3115 const gchar *entry_text = NULL;
3118 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3119 old_length = g_utf8_strlen (entry_text, -1);
3121 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3122 gunichar c = g_utf8_get_char_validated (current, 8);
3123 /* Invalid unichar, stop */
3129 result = g_string_append_unichar (result, c);
3133 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3134 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3137 /* Prevent endless recursion */
3138 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3139 g_signal_emit_by_name (editable, "insert-text",
3140 (gpointer) result->str, (gpointer) result->len,
3141 (gpointer) position, (gpointer) window);
3142 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3146 if (result_len + old_length > 1000) {
3147 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3148 dgettext("hildon-common-strings",
3149 "ckdg_ib_maximum_characters_reached"));
3152 g_string_free (result, TRUE);
3156 text_buffer_insert_text (GtkTextBuffer *buffer,
3159 gint new_text_length,
3160 ModestMsgEditWindow *window)
3162 GString *result = g_string_new ("");
3164 gint result_len = 0;
3165 gboolean changed = FALSE;
3167 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3168 gunichar c = g_utf8_get_char_validated (current, 8);
3169 /* Invalid unichar, stop */
3175 result = g_string_append_c (result, ' ');
3179 result = g_string_append_unichar (result, c);
3185 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3186 g_signal_handlers_block_by_func(G_OBJECT(buffer), G_CALLBACK(text_buffer_insert_text), window);
3187 g_signal_emit_by_name (buffer, "insert-text",
3189 (gpointer) result->str, (gpointer) result->len,
3191 g_signal_handlers_unblock_by_func(G_OBJECT(buffer), G_CALLBACK(text_buffer_insert_text), window);
3194 g_string_free (result, TRUE);
3198 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3201 ModestMsgEditWindowPrivate *priv = NULL;
3203 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3204 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3206 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3209 gtk_widget_show_all (priv->find_toolbar);
3210 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3212 gtk_widget_hide_all (priv->find_toolbar);
3213 gtk_widget_grab_focus (priv->msg_body);
3219 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3221 GtkTextIter *match_start,
3222 GtkTextIter *match_end)
3224 GtkTextIter end_iter;
3225 gchar *str_casefold;
3228 gchar *range_casefold;
3231 gboolean result = FALSE;
3238 gtk_text_iter_forward_to_end (&end_iter);
3240 str_casefold = g_utf8_casefold (str, -1);
3241 str_chars_n = strlen (str);
3243 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3244 range_casefold = g_utf8_casefold (range_text, -1);
3245 range_chars_n = strlen (range_casefold);
3247 if (range_chars_n < str_chars_n) {
3248 g_free (str_casefold);
3249 g_free (range_text);
3250 g_free (range_casefold);
3254 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3255 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3256 if (!g_utf8_collate (range_subtext, str_casefold)) {
3257 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3259 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3260 match_start, match_end, NULL);
3261 g_free (found_text);
3263 g_free (range_subtext);
3267 g_free (str_casefold);
3268 g_free (range_text);
3269 g_free (range_casefold);
3276 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3277 ModestMsgEditWindow *window)
3279 gchar *current_search = NULL;
3280 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3282 GtkTextIter selection_start, selection_end;
3283 GtkTextIter match_start, match_end;
3284 gboolean continue_search = FALSE;
3286 if (message_is_empty (window)) {
3287 g_free (priv->last_search);
3288 priv->last_search = NULL;
3289 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3293 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3294 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3295 g_free (current_search);
3296 g_free (priv->last_search);
3297 priv->last_search = NULL;
3298 /* Information banner about empty search */
3299 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3303 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3304 continue_search = TRUE;
3306 g_free (priv->last_search);
3307 priv->last_search = g_strdup (current_search);
3310 if (continue_search) {
3311 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3312 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3313 &match_start, &match_end);
3315 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3317 GtkTextIter buffer_start;
3318 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3319 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3320 &match_start, &match_end);
3322 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3325 /* Mark as selected the string found in search */
3327 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3328 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3330 g_free (priv->last_search);
3331 priv->last_search = NULL;
3333 g_free (current_search);
3337 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3338 ModestMsgEditWindow *window)
3340 GtkToggleAction *toggle;
3341 ModestWindowPrivate *parent_priv;
3342 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3344 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3345 gtk_toggle_action_set_active (toggle, FALSE);
3349 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3351 ModestMsgEditWindowPrivate *priv;
3353 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3358 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3361 ModestMsgEditWindowPrivate *priv;
3363 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3369 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3372 ModestMsgEditWindowPrivate *priv;
3373 TnyHeader *header = NULL;
3375 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3376 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3378 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3379 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3381 if (priv->draft_msg != NULL) {
3382 g_object_unref (priv->draft_msg);
3385 if (draft != NULL) {
3386 g_object_ref (draft);
3387 header = tny_msg_get_header (draft);
3388 if (priv->msg_uid) {
3389 g_free (priv->msg_uid);
3390 priv->msg_uid = NULL;
3392 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3393 if (GTK_WIDGET_REALIZED (window))
3394 modest_window_mgr_register_window (mgr, MODEST_WINDOW (window));
3397 priv->draft_msg = draft;
3401 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3402 GtkTextIter *start, GtkTextIter *end,
3405 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3406 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3409 if (tag == NULL+13) return;
3410 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3411 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3412 replace_with_images (window, priv->images);
3417 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3420 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3422 g_return_if_fail (TNY_IS_MIME_PART (part));
3423 tny_list_prepend (priv->attachments, (GObject *) part);
3424 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3425 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3426 gtk_widget_show_all (priv->attachments_caption);
3427 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3431 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3433 ModestMsgEditWindowPrivate *priv;
3435 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3436 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3438 return priv->msg_uid;
3442 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3443 ModestMsgEditWindowWidgetType widget_type)
3445 ModestMsgEditWindowPrivate *priv;
3447 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3448 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3450 switch (widget_type) {
3451 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3452 return priv->msg_body;
3454 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3455 return priv->to_field;
3457 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3458 return priv->cc_field;
3460 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3461 return priv->bcc_field;
3463 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3464 return priv->subject_field;
3466 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3467 return priv->attachments_view;
3475 remove_tags (WPTextBuffer *buffer)
3477 GtkTextIter start, end;
3479 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3480 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3482 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3486 on_account_removed (TnyAccountStore *account_store,
3487 TnyAccount *account,
3490 /* Do nothing if it's a store account, because we use the
3491 transport to send the messages */
3492 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3493 const gchar *parent_acc = NULL;
3494 const gchar *our_acc = NULL;
3496 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3497 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3498 /* Close this window if I'm showing a message of the removed account */
3499 if (strcmp (parent_acc, our_acc) == 0)
3500 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3505 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3507 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3509 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3515 set_zoom_do_nothing (ModestWindow *window,
3521 get_zoom_do_nothing (ModestWindow *window)