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);
1014 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1016 TnyMimePart *parent = NULL;
1017 const gchar *content_type = NULL;
1018 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1020 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1022 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1023 parent = g_object_ref (msg);
1024 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1025 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1028 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1029 iter = tny_list_create_iterator (parts);
1030 while (!tny_iterator_is_done (iter)) {
1032 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1033 content_type = tny_mime_part_get_content_type (part);
1034 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1038 g_object_unref (part);
1040 tny_iterator_next (iter);
1042 g_object_unref (iter);
1043 g_object_unref (parts);
1046 if (parent != NULL) {
1047 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1050 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1051 iter = tny_list_create_iterator (parts);
1052 while (!tny_iterator_is_done (iter)) {
1054 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1055 content_type = tny_mime_part_get_content_type (part);
1056 if (content_type && g_str_has_prefix (content_type, "image/")) {
1057 tny_list_prepend (priv->images, (GObject *) part);
1059 g_object_unref (part);
1060 tny_iterator_next (iter);
1062 g_object_unref (iter);
1063 g_object_unref (parts);
1064 g_object_unref (parent);
1069 update_last_cid (ModestMsgEditWindow *self, TnyList *attachments)
1072 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1074 for (iter = tny_list_create_iterator (attachments) ;
1075 !tny_iterator_is_done (iter);
1076 tny_iterator_next (iter)) {
1077 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1078 const gchar *cid = tny_mime_part_get_content_id (part);
1080 char *invalid = NULL;
1081 gint int_cid = strtol (cid, &invalid, 10);
1082 if ((invalid != NULL) && (*invalid == '\0') && (int_cid > priv->last_cid)) {
1083 priv->last_cid = int_cid;
1086 g_object_unref (part);
1091 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1094 const gchar *to, *cc, *bcc, *subject;
1096 ModestMsgEditWindowPrivate *priv;
1098 TnyHeaderFlags priority_flags;
1099 TnyFolder *msg_folder;
1100 gboolean is_html = FALSE;
1102 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1103 g_return_if_fail (TNY_IS_MSG (msg));
1105 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1107 header = tny_msg_get_header (msg);
1108 to = tny_header_get_to (header);
1109 cc = tny_header_get_cc (header);
1110 bcc = tny_header_get_bcc (header);
1111 subject = tny_header_get_subject (header);
1112 priority_flags = tny_header_get_priority (header);
1115 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1117 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1118 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1119 gtk_widget_show (priv->cc_caption);
1120 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1121 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1122 gtk_widget_hide (priv->cc_caption);
1125 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1126 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1127 gtk_widget_show (priv->bcc_caption);
1128 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1129 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1130 gtk_widget_hide (priv->bcc_caption);
1133 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1134 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1137 update_window_title (self);
1139 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1140 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1142 if ((body == NULL)||(body[0] == '\0')) {
1144 body = modest_text_utils_convert_to_html ("");
1147 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1148 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1151 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1154 /* Add attachments to the view */
1155 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1156 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1157 if (tny_list_get_length (priv->attachments) == 0) {
1158 gtk_widget_hide (priv->attachments_caption);
1160 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1161 gtk_widget_show_all (priv->attachments_caption);
1163 get_related_images (self, msg);
1164 update_last_cid (self, priv->attachments);
1165 update_last_cid (self, priv->images);
1166 replace_with_images (self, priv->images);
1168 if (preserve_is_rich && !is_html) {
1169 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1170 /* Get the default format required from configuration */
1171 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1172 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1175 /* Set the default focus depending on having already a To: field or not */
1176 if ((!to)||(*to == '\0')) {
1177 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1179 gtk_widget_grab_focus (priv->msg_body);
1182 /* TODO: lower priority, select in the From: combo to the
1183 value that comes from msg <- not sure, should it be
1186 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1188 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1189 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1191 modest_msg_edit_window_reset_modified (self);
1193 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1194 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1195 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1196 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1198 if (priv->msg_uid) {
1199 g_free (priv->msg_uid);
1200 priv->msg_uid = NULL;
1203 /* we should set a reference to the incoming message if it is a draft */
1204 msg_folder = tny_msg_get_folder (msg);
1206 if (modest_tny_folder_is_local_folder (msg_folder)) {
1207 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1208 if (type == TNY_FOLDER_TYPE_INVALID)
1209 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1211 if (type == TNY_FOLDER_TYPE_DRAFTS)
1212 priv->draft_msg = g_object_ref(msg);
1213 if (type == TNY_FOLDER_TYPE_OUTBOX)
1214 priv->outbox_msg = g_object_ref(msg);
1215 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1217 g_object_unref (msg_folder);
1222 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1225 GList *item_children, *node;
1226 GtkWidget *bin_child;
1228 bin_child = gtk_bin_get_child (GTK_BIN(item));
1230 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1232 for (node = item_children; node != NULL; node = g_list_next (node)) {
1233 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1234 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1237 g_list_free (item_children);
1241 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1244 GList *item_children, *node;
1246 box = gtk_bin_get_child (GTK_BIN (item));
1247 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1248 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1250 for (node = item_children; node != NULL; node = g_list_next (node)) {
1251 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1252 if (GTK_IS_TOGGLE_BUTTON (node->data))
1253 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1254 else if (GTK_IS_BUTTON (node->data))
1255 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1257 g_list_free (item_children);
1262 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1264 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1265 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1266 GtkWidget *placeholder;
1267 GtkWidget *tool_item;
1272 GtkWidget *sizes_menu;
1273 GtkWidget *fonts_menu;
1274 GSList *radio_group = NULL;
1275 GSList *node = NULL;
1279 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1280 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1282 /* Font color placeholder */
1283 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1284 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1287 tool_item = GTK_WIDGET (gtk_tool_item_new ());
1288 priv->font_color_button = hildon_color_button_new ();
1289 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1290 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1291 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
1292 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1293 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1294 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1295 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1297 G_CALLBACK (modest_msg_edit_window_color_button_change),
1300 /* Font size and face placeholder */
1301 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1302 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1304 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1305 priv->size_tool_button_label = gtk_label_new (NULL);
1306 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1307 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1308 size_text,"</span>", NULL);
1309 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1311 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1312 sizes_menu = gtk_menu_new ();
1313 priv->size_items_group = NULL;
1315 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1316 GtkWidget *size_menu_item;
1318 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1319 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1320 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1321 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1322 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1323 gtk_widget_show (size_menu_item);
1325 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1329 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1330 GtkWidget *item = (GtkWidget *) node->data;
1331 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1335 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1336 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1337 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1338 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1339 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1340 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1341 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1342 priv->font_size_toolitem = tool_item;
1345 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1346 priv->font_tool_button_label = gtk_label_new (NULL);
1347 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1348 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1350 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1351 fonts_menu = gtk_menu_new ();
1352 priv->font_items_group = NULL;
1354 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1355 GtkWidget *font_menu_item;
1356 GtkWidget *child_label;
1358 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1359 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1360 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1361 wp_get_font_name (font_index), "</span>", NULL);
1362 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1365 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1366 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1367 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1368 gtk_widget_show (font_menu_item);
1370 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1373 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1374 GtkWidget *item = (GtkWidget *) node->data;
1375 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1378 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1379 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1380 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1381 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1382 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1383 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1384 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1385 priv->font_face_toolitem = tool_item;
1387 /* Set expand and homogeneous for remaining items */
1388 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1389 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1390 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1391 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1392 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1393 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1394 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1395 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1396 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1398 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1399 will not show the tool items added to the placeholders) */
1400 gtk_widget_show_all (parent_priv->toolbar);
1402 /* Set the no show all *after* showing all items. We do not
1403 want the toolbar to be shown with a show all because it
1404 could go agains the gconf setting regarding showing or not
1405 the toolbar of the editor window */
1406 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1412 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1415 ModestWindowPrivate *parent_priv;
1416 ModestMsgEditWindowPrivate *priv;
1417 ModestPair *account_pair = NULL;
1418 ModestDimmingRulesGroup *menu_rules_group = NULL;
1419 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1420 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1421 ModestWindowMgr *mgr = NULL;
1423 g_return_val_if_fail (msg, NULL);
1424 g_return_val_if_fail (account_name, NULL);
1426 mgr = modest_runtime_get_window_mgr ();
1428 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1430 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1431 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1433 /* Menubar. Update the state of some toggles */
1434 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1435 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1436 priv->from_field_protos = get_transports ();
1437 modest_combo_box_set_pair_list (MODEST_COMBO_BOX (priv->from_field), priv->from_field_protos);
1438 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1439 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1442 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1444 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1446 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1448 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
1449 if (account_pair != NULL)
1450 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
1452 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1453 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1454 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1455 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1456 /* Add common dimming rules */
1457 modest_dimming_rules_group_add_rules (menu_rules_group,
1458 modest_msg_edit_window_menu_dimming_entries,
1459 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1460 MODEST_WINDOW (obj));
1461 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1462 modest_msg_edit_window_toolbar_dimming_entries,
1463 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1464 MODEST_WINDOW (obj));
1465 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1466 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1467 MODEST_WINDOW (obj));
1468 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1469 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1470 MODEST_WINDOW (obj));
1471 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1472 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1473 MODEST_WINDOW (obj));
1474 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1475 modest_msg_edit_window_clipboard_dimming_entries,
1476 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1477 MODEST_WINDOW (obj));
1478 /* Insert dimming rules group for this window */
1479 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1480 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1481 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1482 /* Checks the dimming rules */
1483 g_object_unref (menu_rules_group);
1484 g_object_unref (toolbar_rules_group);
1485 g_object_unref (clipboard_rules_group);
1486 gtk_widget_show_all (GTK_WIDGET (obj));
1488 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1490 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1492 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1493 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1494 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1495 priv->update_caption_visibility = TRUE;
1497 modest_msg_edit_window_reset_modified (MODEST_MSG_EDIT_WINDOW (obj));
1499 /* Track account-removed signal, this window should be closed
1500 in the case we're creating a mail associated to the account
1502 priv->account_removed_handler_id =
1503 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1505 G_CALLBACK(on_account_removed),
1508 return (ModestWindow*) obj;
1512 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1514 GString **string_buffer = (GString **) user_data;
1516 *string_buffer = g_string_append (*string_buffer, buffer);
1522 * @result: A new string which should be freed with g_free().
1525 get_formatted_data (ModestMsgEditWindow *edit_window)
1527 ModestMsgEditWindowPrivate *priv;
1528 GString *string_buffer = g_string_new ("");
1530 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1532 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1534 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1536 return g_string_free (string_buffer, FALSE);
1541 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1544 const gchar *account_name;
1545 ModestMsgEditWindowPrivate *priv;
1546 TnyIterator *att_iter;
1548 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1550 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1552 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1553 g_return_val_if_fail (account_name, NULL);
1556 /* don't free these (except from) */
1557 data = g_slice_new0 (MsgData);
1558 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1560 data->account_name = g_strdup (account_name);
1561 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1562 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1563 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1564 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1565 if (priv->draft_msg) {
1566 data->draft_msg = g_object_ref (priv->draft_msg);
1567 } else if (priv->outbox_msg) {
1568 data->draft_msg = g_object_ref (priv->outbox_msg);
1570 data->draft_msg = NULL;
1573 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1575 gtk_text_buffer_get_bounds (buf, &b, &e);
1576 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1578 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1579 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1581 data->html_body = NULL;
1583 /* deep-copy the data */
1584 att_iter = tny_list_create_iterator (priv->attachments);
1585 data->attachments = NULL;
1586 while (!tny_iterator_is_done (att_iter)) {
1587 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1588 if (!(TNY_IS_MIME_PART(part))) {
1589 g_warning ("strange data in attachment list");
1590 g_object_unref (part);
1591 tny_iterator_next (att_iter);
1594 data->attachments = g_list_append (data->attachments,
1596 tny_iterator_next (att_iter);
1598 g_object_unref (att_iter);
1600 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1601 att_iter = tny_list_create_iterator (priv->images);
1602 data->images = NULL;
1603 while (!tny_iterator_is_done (att_iter)) {
1604 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1606 if (!(TNY_IS_MIME_PART(part))) {
1607 g_warning ("strange data in attachment list");
1608 g_object_unref (part);
1609 tny_iterator_next (att_iter);
1612 cid = tny_mime_part_get_content_id (part);
1614 gchar *image_tag_id;
1615 GtkTextTag *image_tag;
1617 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1618 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1619 g_free (image_tag_id);
1621 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1623 ((gtk_text_iter_has_tag (&iter, image_tag))||
1624 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1625 data->images = g_list_append (data->images,
1626 g_object_ref (part));
1628 g_object_unref (part);
1629 tny_iterator_next (att_iter);
1632 data->priority_flags = priv->priority_flags;
1639 unref_gobject (GObject *obj, gpointer data)
1641 if (!G_IS_OBJECT(obj))
1643 g_object_unref (obj);
1647 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1650 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1658 g_free (data->from);
1659 g_free (data->subject);
1660 g_free (data->plain_body);
1661 g_free (data->html_body);
1662 g_free (data->account_name);
1664 if (data->draft_msg != NULL) {
1665 g_object_unref (data->draft_msg);
1666 data->draft_msg = NULL;
1669 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1670 g_list_free (data->attachments);
1671 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1672 g_list_free (data->images);
1674 g_slice_free (MsgData, data);
1678 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1680 guint64 *parts_size)
1682 ModestMsgEditWindowPrivate *priv;
1684 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1686 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1688 /* TODO: add images */
1689 *parts_size += priv->images_size;
1690 *parts_count += priv->images_count;
1695 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1698 ModestMsgEditWindowPrivate *priv = NULL;
1699 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1701 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1703 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1705 return MODEST_MSG_EDIT_FORMAT_HTML;
1707 return MODEST_MSG_EDIT_FORMAT_TEXT;
1711 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1712 ModestMsgEditFormat format)
1714 ModestMsgEditWindowPrivate *priv;
1716 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1717 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1720 case MODEST_MSG_EDIT_FORMAT_HTML:
1721 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1723 case MODEST_MSG_EDIT_FORMAT_TEXT:
1724 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1727 g_return_if_reached ();
1731 ModestMsgEditFormatState *
1732 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1734 ModestMsgEditFormatState *format_state = NULL;
1735 ModestMsgEditWindowPrivate *priv;
1736 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1738 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1739 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1741 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1743 format_state = g_new0 (ModestMsgEditFormatState, 1);
1744 format_state->bold = buffer_format->bold&0x1;
1745 format_state->italics = buffer_format->italic&0x1;
1746 format_state->bullet = buffer_format->bullet&0x1;
1747 format_state->color = buffer_format->color;
1748 format_state->font_size = buffer_format->font_size;
1749 format_state->font_family = wp_get_font_name (buffer_format->font);
1750 format_state->justification = buffer_format->justification;
1751 g_free (buffer_format);
1753 return format_state;
1758 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1759 const ModestMsgEditFormatState *format_state)
1761 ModestMsgEditWindowPrivate *priv;
1762 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1763 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1764 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1765 g_return_if_fail (format_state != NULL);
1767 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1768 gtk_widget_grab_focus (priv->msg_body);
1769 buffer_format->bold = (format_state->bold != FALSE);
1770 buffer_format->italic = (format_state->italics != FALSE);
1771 buffer_format->color = format_state->color;
1772 buffer_format->font_size = format_state->font_size;
1773 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1774 buffer_format->justification = format_state->justification;
1775 buffer_format->bullet = format_state->bullet;
1777 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1779 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1780 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1781 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1782 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1783 buffer_format->cs.font = (buffer_format->font != current_format->font);
1784 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1785 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1787 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1788 if (buffer_format->cs.bold) {
1789 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1790 GINT_TO_POINTER (buffer_format->bold&0x1));
1792 if (buffer_format->cs.italic) {
1793 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1794 GINT_TO_POINTER (buffer_format->italic&0x1));
1796 if (buffer_format->cs.color) {
1797 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1798 GINT_TO_POINTER (&(buffer_format->color)));
1800 if (buffer_format->cs.font_size) {
1801 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1802 GINT_TO_POINTER (buffer_format->font_size));
1804 if (buffer_format->cs.justification) {
1805 switch (buffer_format->justification) {
1806 case GTK_JUSTIFY_LEFT:
1807 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1808 GINT_TO_POINTER(TRUE));
1810 case GTK_JUSTIFY_CENTER:
1811 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1812 GINT_TO_POINTER(TRUE));
1814 case GTK_JUSTIFY_RIGHT:
1815 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1816 GINT_TO_POINTER(TRUE));
1823 if (buffer_format->cs.font) {
1824 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1825 GINT_TO_POINTER (buffer_format->font));
1827 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1828 if (buffer_format->cs.bullet) {
1829 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1830 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1832 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1834 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1836 g_free (current_format);
1841 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1843 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1845 ModestWindowPrivate *parent_priv;
1846 ModestMsgEditWindowPrivate *priv;
1847 GtkWidget *new_size_menuitem;
1848 GtkWidget *new_font_menuitem;
1850 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1851 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1853 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1854 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1855 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1856 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1858 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
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);
1863 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1865 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1866 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1868 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1869 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1871 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1872 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1875 switch (buffer_format->justification)
1877 case GTK_JUSTIFY_LEFT:
1878 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentLeftMenu");
1880 case GTK_JUSTIFY_CENTER:
1881 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentCenterMenu");
1883 case GTK_JUSTIFY_RIGHT:
1884 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentRightMenu");
1891 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1893 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1894 G_CALLBACK (modest_msg_edit_window_color_button_change),
1896 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1897 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1898 G_CALLBACK (modest_msg_edit_window_color_button_change),
1901 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1902 buffer_format->font_size))->data);
1903 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1907 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1908 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1909 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1911 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1912 G_CALLBACK (modest_msg_edit_window_size_change),
1914 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1915 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1916 G_CALLBACK (modest_msg_edit_window_size_change),
1920 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1921 buffer_format->font))->data);
1922 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1926 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1927 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1928 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1930 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1931 G_CALLBACK (modest_msg_edit_window_font_change),
1933 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1934 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1935 G_CALLBACK (modest_msg_edit_window_font_change),
1939 g_free (buffer_format);
1943 #ifdef MODEST_HILDON_VERSION_0
1945 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1948 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1949 ModestMsgEditWindowPrivate *priv;
1950 GtkWidget *dialog = NULL;
1952 GdkColor *new_color = NULL;
1954 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1955 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1957 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1958 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1959 g_free (buffer_format);
1961 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
1962 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1963 if (new_color != NULL) {
1964 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1965 (gpointer) new_color);
1968 gtk_widget_destroy (dialog);
1973 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1976 ModestMsgEditWindowPrivate *priv;
1977 GtkWidget *dialog = NULL;
1979 GdkColor *old_color = NULL;
1980 const GdkColor *new_color = NULL;
1982 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1983 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1985 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1986 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1988 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
1989 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1990 if (new_color != NULL)
1991 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1993 gtk_widget_destroy (dialog);
1999 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2002 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2003 ModestMsgEditWindowPrivate *priv;
2004 GtkWidget *dialog = NULL;
2006 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2007 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2009 dialog = hildon_color_chooser_new ();
2010 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2011 g_free (buffer_format);
2013 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2015 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2016 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2019 gtk_widget_destroy (dialog);
2024 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2027 ModestMsgEditWindowPrivate *priv;
2028 GtkWidget *dialog = NULL;
2029 GdkColor *old_color = NULL;
2031 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2032 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2034 dialog = hildon_color_chooser_new ();
2035 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2037 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2039 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2040 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2042 gtk_widget_destroy (dialog);
2045 #endif /*!MODEST_HILDON_VERSION_0*/
2049 static TnyStream* create_stream_for_uri (const gchar* uri)
2054 TnyStream *result = NULL;
2056 GnomeVFSHandle *handle = NULL;
2057 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2058 if (test == GNOME_VFS_OK) {
2059 /* Create the tinymail stream: */
2060 /* Presumably tinymai will call gnome_vfs_close (handle) later. */
2061 result = TNY_STREAM (tny_vfs_stream_new (handle));
2068 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2071 ModestMsgEditWindowPrivate *priv;
2072 GtkWidget *dialog = NULL;
2074 GSList *uris = NULL;
2075 GSList *uri_node = NULL;
2077 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2079 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2080 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2081 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2083 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2085 response = gtk_dialog_run (GTK_DIALOG (dialog));
2087 case GTK_RESPONSE_OK:
2088 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2093 gtk_widget_destroy (dialog);
2095 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2097 GnomeVFSHandle *handle = NULL;
2098 GnomeVFSResult result;
2099 GtkTextIter position;
2100 GtkTextMark *insert_mark;
2102 uri = (const gchar *) uri_node->data;
2103 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2104 if (result == GNOME_VFS_OK) {
2106 GnomeVFSFileInfo *info;
2107 gchar *filename, *basename, *escaped_filename;
2108 TnyMimePart *mime_part;
2110 const gchar *mime_type = NULL;
2111 GnomeVFSURI *vfs_uri;
2112 guint64 stream_size;
2114 vfs_uri = gnome_vfs_uri_new (uri);
2116 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2117 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2118 g_free (escaped_filename);
2119 gnome_vfs_uri_unref (vfs_uri);
2120 info = gnome_vfs_file_info_new ();
2122 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2123 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2125 mime_type = gnome_vfs_file_info_get_mime_type (info);
2127 mime_part = tny_platform_factory_new_mime_part
2128 (modest_runtime_get_platform_factory ());
2130 TnyStream *stream = create_stream_for_uri (uri);
2131 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2133 content_id = g_strdup_printf ("%d", priv->last_cid);
2134 tny_mime_part_set_content_id (mime_part, content_id);
2135 g_free (content_id);
2138 basename = g_path_get_basename (filename);
2139 tny_mime_part_set_filename (mime_part, basename);
2142 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2144 if (pixbuf != NULL) {
2145 priv->images_size += stream_size;
2146 priv->images_count ++;
2147 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2148 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2149 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2152 tny_list_prepend (priv->images, (GObject *) mime_part);
2153 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2155 g_object_unref (mime_part);
2156 gnome_vfs_file_info_unref (info);
2165 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2167 GtkWidget *dialog = NULL;
2169 GSList *uris = NULL;
2172 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2173 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2174 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2176 response = gtk_dialog_run (GTK_DIALOG (dialog));
2178 case GTK_RESPONSE_OK:
2179 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2184 gtk_widget_destroy (dialog);
2186 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2187 const gchar *uri = (const gchar *) uri_node->data;
2188 modest_msg_edit_window_attach_file_one (window, uri);
2190 g_slist_foreach (uris, (GFunc) g_free, NULL);
2191 g_slist_free (uris);
2195 modest_msg_edit_window_attach_file_one (
2196 ModestMsgEditWindow *window,
2199 g_return_if_fail (window);
2200 g_return_if_fail (uri);
2202 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2205 GnomeVFSHandle *handle = NULL;
2206 GnomeVFSResult result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2207 if (result == GNOME_VFS_OK) {
2208 TnyMimePart *mime_part;
2210 const gchar *mime_type = NULL;
2212 gchar *escaped_filename;
2215 GnomeVFSFileInfo *info;
2216 GnomeVFSURI *vfs_uri;
2218 vfs_uri = gnome_vfs_uri_new (uri);
2221 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2222 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2223 g_free (escaped_filename);
2224 gnome_vfs_uri_unref (vfs_uri);
2226 info = gnome_vfs_file_info_new ();
2228 if (gnome_vfs_get_file_info (uri,
2230 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2232 mime_type = gnome_vfs_file_info_get_mime_type (info);
2233 mime_part = tny_platform_factory_new_mime_part
2234 (modest_runtime_get_platform_factory ());
2235 stream = TNY_STREAM (tny_vfs_stream_new (handle));
2237 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2239 g_object_unref (stream);
2241 content_id = g_strdup_printf ("%d", priv->last_cid);
2242 tny_mime_part_set_content_id (mime_part, content_id);
2243 g_free (content_id);
2246 basename = g_path_get_basename (filename);
2247 tny_mime_part_set_filename (mime_part, basename);
2250 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2251 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2253 info->size == 0, info->size);
2254 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2255 gtk_widget_show_all (priv->attachments_caption);
2256 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2258 g_object_unref (mime_part);
2259 gnome_vfs_file_info_unref (info);
2264 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2267 ModestMsgEditWindowPrivate *priv;
2270 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2271 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2273 if (att_list == NULL) {
2274 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2276 g_object_ref (att_list);
2279 if (tny_list_get_length (att_list) == 0) {
2280 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2282 GtkWidget *confirmation_dialog = NULL;
2283 gboolean dialog_response;
2284 gchar *message = NULL;
2285 gchar *filename = NULL;
2287 if (tny_list_get_length (att_list) == 1) {
2289 iter = tny_list_create_iterator (att_list);
2290 part = (TnyMimePart *) tny_iterator_get_current (iter);
2291 g_object_unref (iter);
2292 if (TNY_IS_MSG (part)) {
2293 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2295 filename = g_strdup (tny_header_get_subject (header));
2296 g_object_unref (header);
2298 if (filename == NULL) {
2299 filename = g_strdup (_("mail_va_no_subject"));
2302 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2304 g_object_unref (part);
2306 filename = g_strdup ("");
2308 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2309 (tny_list_get_length (att_list) == 1)), filename);
2311 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
2313 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
2314 gtk_widget_destroy (confirmation_dialog);
2315 if (!dialog_response) {
2316 g_object_unref (att_list);
2319 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
2321 for (iter = tny_list_create_iterator (att_list);
2322 !tny_iterator_is_done (iter);
2323 tny_iterator_next (iter)) {
2324 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2325 const gchar *att_id;
2326 tny_list_remove (priv->attachments, (GObject *) mime_part);
2328 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2330 if (tny_list_get_length (priv->attachments) == 0)
2331 gtk_widget_hide (priv->attachments_caption);
2332 att_id = tny_mime_part_get_content_id (mime_part);
2334 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2336 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2337 g_object_unref (mime_part);
2341 g_object_unref (att_list);
2343 /* if the last attachment has been removed, focus the Subject: field */
2344 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2345 gtk_widget_grab_focus (priv->subject_field);
2349 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2352 ModestMsgEditWindowPrivate *priv;
2353 GdkColor *new_color;
2354 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2356 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2357 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2360 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2362 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2364 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2366 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2371 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2374 ModestMsgEditWindowPrivate *priv;
2375 gint new_size_index;
2376 ModestMsgEditWindow *window;
2379 window = MODEST_MSG_EDIT_WINDOW (userdata);
2380 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2381 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2383 if (gtk_check_menu_item_get_active (menu_item)) {
2385 WPTextBufferFormat format;
2387 memset (&format, 0, sizeof (format));
2388 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2390 label = gtk_bin_get_child (GTK_BIN (menu_item));
2392 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2393 format.cs.font_size = TRUE;
2394 format.cs.text_position = TRUE;
2395 format.cs.font = TRUE;
2396 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2397 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2399 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2400 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2401 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2403 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2404 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2405 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2411 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2414 ModestMsgEditWindowPrivate *priv;
2415 gint new_font_index;
2416 ModestMsgEditWindow *window;
2419 window = MODEST_MSG_EDIT_WINDOW (userdata);
2420 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2421 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2423 if (gtk_check_menu_item_get_active (menu_item)) {
2426 label = gtk_bin_get_child (GTK_BIN (menu_item));
2428 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2430 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2431 GINT_TO_POINTER(new_font_index)))
2432 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2434 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2435 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2436 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2442 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2444 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2445 ModestWindowPrivate *parent_priv;
2446 ModestWindowMgr *mgr;
2447 gboolean is_fullscreen;
2448 GtkAction *fs_toggle_action;
2451 mgr = modest_runtime_get_window_mgr ();
2452 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2454 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2456 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2457 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2458 if (is_fullscreen != active)
2459 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2467 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2470 ModestMsgEditWindowPrivate *priv = NULL;
2471 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2473 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2474 if (!priv->update_caption_visibility)
2477 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2479 gtk_widget_show (priv->cc_caption);
2481 gtk_widget_hide (priv->cc_caption);
2483 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2487 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2490 ModestMsgEditWindowPrivate *priv = NULL;
2491 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2493 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2494 if (!priv->update_caption_visibility)
2497 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2499 gtk_widget_show (priv->bcc_caption);
2501 gtk_widget_hide (priv->bcc_caption);
2503 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2507 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2508 ModestRecptEditor *editor)
2510 ModestMsgEditWindowPrivate *priv;
2512 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2513 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2514 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2516 if (editor == NULL) {
2517 GtkWidget *view_focus;
2518 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2520 /* This code should be kept in sync with ModestRecptEditor. The
2521 textview inside the recpt editor is the one that really gets the
2522 focus. As it's inside a scrolled window, and this one inside the
2523 hbox recpt editor inherits from, we'll need to go up in the
2524 hierarchy to know if the text view is part of the recpt editor
2525 or if it's a different text entry */
2527 if (gtk_widget_get_parent (view_focus)) {
2528 GtkWidget *first_parent;
2530 first_parent = gtk_widget_get_parent (view_focus);
2531 if (gtk_widget_get_parent (first_parent) &&
2532 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2533 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2538 editor = MODEST_RECPT_EDITOR (priv->to_field);
2542 modest_address_book_select_addresses (editor);
2547 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2549 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2551 modest_msg_edit_window_open_addressbook (window, NULL);
2555 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2556 gboolean show_toolbar)
2558 ModestWindowPrivate *parent_priv;
2559 const gchar *action_name;
2562 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2563 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2565 /* We can not just use the code of
2566 modest_msg_edit_window_setup_toolbar because it has a
2567 mixture of both initialization and creation code. */
2569 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2571 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2573 /* Update also the actions (to update the toggles in the
2574 menus), we have to do it manually because some other window
2575 of the same time could have changed it (remember that the
2576 toolbar fullscreen mode is shared by all the windows of the
2578 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2579 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2581 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2583 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2584 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2590 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2591 TnyHeaderFlags priority_flags)
2593 ModestMsgEditWindowPrivate *priv;
2594 ModestWindowPrivate *parent_priv;
2596 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2598 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2599 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2601 if (priv->priority_flags != priority_flags) {
2602 GtkAction *priority_action = NULL;
2604 priv->priority_flags = priority_flags;
2606 switch (priority_flags) {
2607 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2608 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2609 gtk_widget_show (priv->priority_icon);
2610 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2611 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2613 case TNY_HEADER_FLAG_LOW_PRIORITY:
2614 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2615 gtk_widget_show (priv->priority_icon);
2616 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2617 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2620 gtk_widget_hide (priv->priority_icon);
2621 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2622 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2625 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2626 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2631 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2634 ModestMsgEditWindowPrivate *priv;
2635 ModestWindowPrivate *parent_priv;
2636 gint current_format;
2638 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2640 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2641 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2643 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2644 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2646 if (current_format != file_format) {
2647 switch (file_format) {
2648 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2649 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2650 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2652 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2656 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2657 response = gtk_dialog_run (GTK_DIALOG (dialog));
2658 gtk_widget_destroy (dialog);
2659 if (response == GTK_RESPONSE_OK) {
2660 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2662 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2663 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2668 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2673 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2676 ModestMsgEditWindowPrivate *priv;
2677 WPTextBufferFormat oldfmt, fmt;
2678 gint old_position = 0;
2682 GdkColor *color = NULL;
2683 gboolean bold, bold_set, italic, italic_set;
2684 gboolean underline, underline_set;
2685 gboolean strikethrough, strikethrough_set;
2686 gboolean position_set;
2687 gboolean font_size_set, font_set, color_set;
2690 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2691 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2693 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2695 /* First we get the currently selected font information */
2696 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2698 switch (oldfmt.text_position) {
2699 case TEXT_POSITION_NORMAL:
2702 case TEXT_POSITION_SUPERSCRIPT:
2710 g_object_set (G_OBJECT (dialog),
2711 "bold", oldfmt.bold != FALSE,
2712 "bold-set", !oldfmt.cs.bold,
2713 "underline", oldfmt.underline != FALSE,
2714 "underline-set", !oldfmt.cs.underline,
2715 "italic", oldfmt.italic != FALSE,
2716 "italic-set", !oldfmt.cs.italic,
2717 "strikethrough", oldfmt.strikethrough != FALSE,
2718 "strikethrough-set", !oldfmt.cs.strikethrough,
2719 "color", &oldfmt.color,
2720 "color-set", !oldfmt.cs.color,
2721 "size", wp_font_size[oldfmt.font_size],
2722 "size-set", !oldfmt.cs.font_size,
2723 "position", old_position,
2724 "position-set", !oldfmt.cs.text_position,
2725 "family", wp_get_font_name (oldfmt.font),
2726 "family-set", !oldfmt.cs.font,
2729 gtk_widget_show_all (dialog);
2730 response = gtk_dialog_run (GTK_DIALOG (dialog));
2731 if (response == GTK_RESPONSE_OK) {
2733 g_object_get( dialog,
2735 "bold-set", &bold_set,
2736 "underline", &underline,
2737 "underline-set", &underline_set,
2739 "italic-set", &italic_set,
2740 "strikethrough", &strikethrough,
2741 "strikethrough-set", &strikethrough_set,
2743 "color-set", &color_set,
2745 "size-set", &font_size_set,
2746 "family", &font_name,
2747 "family-set", &font_set,
2748 "position", &position,
2749 "position-set", &position_set,
2754 if (response == GTK_RESPONSE_OK) {
2755 memset(&fmt, 0, sizeof(fmt));
2761 fmt.italic = italic;
2762 fmt.cs.italic = TRUE;
2764 if (underline_set) {
2765 fmt.underline = underline;
2766 fmt.cs.underline = TRUE;
2768 if (strikethrough_set) {
2769 fmt.strikethrough = strikethrough;
2770 fmt.cs.strikethrough = TRUE;
2775 ? TEXT_POSITION_NORMAL
2776 : ( ( position == 1 )
2777 ? TEXT_POSITION_SUPERSCRIPT
2778 : TEXT_POSITION_SUBSCRIPT );
2779 fmt.cs.text_position = TRUE;
2780 fmt.font_size = oldfmt.font_size;
2784 fmt.cs.color = TRUE;
2787 fmt.font = wp_get_font_index(font_name,
2792 if (font_size_set) {
2793 fmt.cs.font_size = TRUE;
2794 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2796 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2797 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2799 gtk_widget_destroy (dialog);
2801 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2805 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2807 ModestMsgEditWindowPrivate *priv;
2809 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2810 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2812 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2814 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2815 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2820 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2822 ModestMsgEditWindowPrivate *priv;
2824 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2825 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2827 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2829 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2830 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2835 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2837 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2839 priv->can_undo = can_undo;
2843 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2845 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2847 priv->can_redo = can_redo;
2851 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2853 ModestMsgEditWindowPrivate *priv;
2854 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2855 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2857 return priv->can_undo;
2861 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2863 ModestMsgEditWindowPrivate *priv;
2864 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2865 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2867 return priv->can_redo;
2872 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2875 GtkTextIter match_start, match_end;
2877 if (image_id == NULL)
2880 gtk_text_buffer_get_start_iter (buffer, &iter);
2882 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2883 GSList *tags = gtk_text_iter_get_tags (&match_start);
2885 for (node = tags; node != NULL; node = g_slist_next (node)) {
2886 GtkTextTag *tag = (GtkTextTag *) node->data;
2887 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2888 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2889 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2891 offset = gtk_text_iter_get_offset (&match_start);
2892 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2893 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2897 gtk_text_iter_forward_char (&iter);
2902 message_is_empty (ModestMsgEditWindow *window)
2904 ModestMsgEditWindowPrivate *priv = NULL;
2906 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2907 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2909 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
2910 * so we can ignore markup.
2912 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
2915 count = gtk_text_buffer_get_char_count (buf);
2921 msg_body_focus (GtkWidget *focus,
2922 GdkEventFocus *event,
2926 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
2927 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
2928 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
2933 recpt_field_changed (GtkTextBuffer *buffer,
2934 ModestMsgEditWindow *editor)
2936 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
2937 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
2941 body_changed (GtkTextBuffer *buffer, 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 modest_msg_edit_window_reset_modified (ModestMsgEditWindow *editor)
2950 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2951 GtkTextBuffer *buffer;
2953 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2954 gtk_text_buffer_set_modified (buffer, FALSE);
2955 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2956 gtk_text_buffer_set_modified (buffer, FALSE);
2957 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2958 gtk_text_buffer_set_modified (buffer, FALSE);
2959 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2963 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2965 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2966 GtkTextBuffer *buffer;
2968 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2969 if (gtk_text_buffer_get_modified (buffer))
2971 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2972 if (gtk_text_buffer_get_modified (buffer))
2974 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2975 if (gtk_text_buffer_get_modified (buffer))
2977 if (gtk_text_buffer_get_modified (priv->text_buffer))
2987 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
2989 ModestMsgEditWindowPrivate *priv = NULL;
2991 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2992 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2994 /* check if there's no recipient added */
2995 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2996 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2997 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2998 /* no recipient contents, then select contacts */
2999 modest_msg_edit_window_open_addressbook (window, NULL);
3003 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3004 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3007 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3008 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3011 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3012 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3016 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3017 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3018 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3025 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3026 ModestMsgEditWindow *window)
3028 modest_msg_edit_window_offer_attach_file (window);
3032 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3034 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3036 return priv->clipboard_text;
3040 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3042 ModestMsgEditWindow *window)
3044 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3045 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3047 if (!GTK_WIDGET_VISIBLE (window))
3050 text = gtk_clipboard_wait_for_text (selection_clipboard);
3052 if (priv->clipboard_text != NULL) {
3053 g_free (priv->clipboard_text);
3055 priv->clipboard_text = text;
3057 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3060 subject_field_move_cursor (GtkEntry *entry,
3061 GtkMovementStep step,
3066 if (!GTK_WIDGET_VISIBLE (window))
3069 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3073 update_window_title (ModestMsgEditWindow *window)
3075 ModestMsgEditWindowPrivate *priv = NULL;
3076 const gchar *subject;
3078 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3079 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3080 if (subject == NULL || subject[0] == '\0')
3081 subject = _("mail_va_new_email");
3083 gtk_window_set_title (GTK_WINDOW (window), subject);
3088 subject_field_changed (GtkEditable *editable,
3089 ModestMsgEditWindow *window)
3091 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3092 update_window_title (window);
3093 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3094 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3095 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3099 subject_field_insert_text (GtkEditable *editable,
3101 gint new_text_length,
3103 ModestMsgEditWindow *window)
3105 GString *result = g_string_new ("");
3107 gint result_len = 0;
3108 const gchar *entry_text = NULL;
3111 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3112 old_length = g_utf8_strlen (entry_text, -1);
3114 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3115 gunichar c = g_utf8_get_char_validated (current, 8);
3116 /* Invalid unichar, stop */
3122 result = g_string_append_unichar (result, c);
3126 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3127 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3130 /* Prevent endless recursion */
3131 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3132 g_signal_emit_by_name (editable, "insert-text",
3133 (gpointer) result->str, (gpointer) result->len,
3134 (gpointer) position, (gpointer) window);
3135 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3139 if (result_len + old_length > 1000) {
3140 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3141 dgettext("hildon-common-strings",
3142 "ckdg_ib_maximum_characters_reached"));
3145 g_string_free (result, TRUE);
3149 text_buffer_insert_text (GtkTextBuffer *buffer,
3152 gint new_text_length,
3153 ModestMsgEditWindow *window)
3155 GString *result = g_string_new ("");
3157 gint result_len = 0;
3158 gboolean changed = FALSE;
3160 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3161 gunichar c = g_utf8_get_char_validated (current, 8);
3162 /* Invalid unichar, stop */
3168 result = g_string_append_c (result, ' ');
3172 result = g_string_append_unichar (result, c);
3178 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3179 g_signal_handlers_block_by_func(G_OBJECT(buffer), G_CALLBACK(text_buffer_insert_text), window);
3180 g_signal_emit_by_name (buffer, "insert-text",
3182 (gpointer) result->str, (gpointer) result->len,
3184 g_signal_handlers_unblock_by_func(G_OBJECT(buffer), G_CALLBACK(text_buffer_insert_text), window);
3187 g_string_free (result, TRUE);
3191 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3194 ModestMsgEditWindowPrivate *priv = NULL;
3196 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3197 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3199 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3202 gtk_widget_show_all (priv->find_toolbar);
3203 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3205 gtk_widget_hide_all (priv->find_toolbar);
3206 gtk_widget_grab_focus (priv->msg_body);
3212 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3214 GtkTextIter *match_start,
3215 GtkTextIter *match_end)
3217 GtkTextIter end_iter;
3218 gchar *str_casefold;
3221 gchar *range_casefold;
3224 gboolean result = FALSE;
3231 gtk_text_iter_forward_to_end (&end_iter);
3233 str_casefold = g_utf8_casefold (str, -1);
3234 str_chars_n = strlen (str);
3236 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3237 range_casefold = g_utf8_casefold (range_text, -1);
3238 range_chars_n = strlen (range_casefold);
3240 if (range_chars_n < str_chars_n) {
3241 g_free (str_casefold);
3242 g_free (range_text);
3243 g_free (range_casefold);
3247 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3248 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3249 if (!g_utf8_collate (range_subtext, str_casefold)) {
3250 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3252 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3253 match_start, match_end, NULL);
3254 g_free (found_text);
3256 g_free (range_subtext);
3260 g_free (str_casefold);
3261 g_free (range_text);
3262 g_free (range_casefold);
3269 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3270 ModestMsgEditWindow *window)
3272 gchar *current_search = NULL;
3273 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3275 GtkTextIter selection_start, selection_end;
3276 GtkTextIter match_start, match_end;
3277 gboolean continue_search = FALSE;
3279 if (message_is_empty (window)) {
3280 g_free (priv->last_search);
3281 priv->last_search = NULL;
3282 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3286 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3287 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3288 g_free (current_search);
3289 g_free (priv->last_search);
3290 priv->last_search = NULL;
3291 /* Information banner about empty search */
3292 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3296 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3297 continue_search = TRUE;
3299 g_free (priv->last_search);
3300 priv->last_search = g_strdup (current_search);
3303 if (continue_search) {
3304 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3305 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3306 &match_start, &match_end);
3308 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3310 GtkTextIter buffer_start;
3311 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3312 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3313 &match_start, &match_end);
3315 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3318 /* Mark as selected the string found in search */
3320 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3321 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3323 g_free (priv->last_search);
3324 priv->last_search = NULL;
3326 g_free (current_search);
3330 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3331 ModestMsgEditWindow *window)
3333 GtkToggleAction *toggle;
3334 ModestWindowPrivate *parent_priv;
3335 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3337 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3338 gtk_toggle_action_set_active (toggle, FALSE);
3342 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3344 ModestMsgEditWindowPrivate *priv;
3346 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3351 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3354 ModestMsgEditWindowPrivate *priv;
3356 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3362 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3365 ModestMsgEditWindowPrivate *priv;
3366 TnyHeader *header = NULL;
3368 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3369 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3371 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3372 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3374 if (priv->draft_msg != NULL) {
3375 g_object_unref (priv->draft_msg);
3378 if (draft != NULL) {
3379 g_object_ref (draft);
3380 header = tny_msg_get_header (draft);
3381 if (priv->msg_uid) {
3382 g_free (priv->msg_uid);
3383 priv->msg_uid = NULL;
3385 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3386 if (GTK_WIDGET_REALIZED (window))
3387 modest_window_mgr_register_window (mgr, MODEST_WINDOW (window));
3390 priv->draft_msg = draft;
3394 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3395 GtkTextIter *start, GtkTextIter *end,
3398 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3399 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3402 if (tag == NULL+13) return;
3403 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3404 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3405 replace_with_images (window, priv->images);
3410 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3413 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3415 g_return_if_fail (TNY_IS_MIME_PART (part));
3416 tny_list_prepend (priv->attachments, (GObject *) part);
3417 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3418 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3419 gtk_widget_show_all (priv->attachments_caption);
3420 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3424 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3426 ModestMsgEditWindowPrivate *priv;
3428 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3429 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3431 return priv->msg_uid;
3435 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3436 ModestMsgEditWindowWidgetType widget_type)
3438 ModestMsgEditWindowPrivate *priv;
3440 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3441 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3443 switch (widget_type) {
3444 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3445 return priv->msg_body;
3447 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3448 return priv->to_field;
3450 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3451 return priv->cc_field;
3453 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3454 return priv->bcc_field;
3456 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3457 return priv->subject_field;
3459 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3460 return priv->attachments_view;
3468 remove_tags (WPTextBuffer *buffer)
3470 GtkTextIter start, end;
3472 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3473 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3475 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3479 on_account_removed (TnyAccountStore *account_store,
3480 TnyAccount *account,
3483 /* Do nothing if it's a store account, because we use the
3484 transport to send the messages */
3485 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3486 const gchar *parent_acc = NULL;
3487 const gchar *our_acc = NULL;
3489 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3490 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3491 /* Close this window if I'm showing a message of the removed account */
3492 if (strcmp (parent_acc, our_acc) == 0)
3493 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3498 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3500 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3502 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3508 set_zoom_do_nothing (ModestWindow *window,
3514 get_zoom_do_nothing (ModestWindow *window)