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-address-book.h"
60 #include "modest-text-utils.h"
61 #include <tny-simple-list.h>
62 #include <wptextview.h>
63 #include <wptextbuffer.h>
64 #include "modest-scroll-area.h"
66 #include "modest-hildon-includes.h"
67 #ifdef MODEST_HAVE_HILDON0_WIDGETS
68 #include <hildon-widgets/hildon-color-chooser.h>
70 #include "widgets/modest-msg-edit-window-ui.h"
71 #ifdef MODEST_HAVE_HILDON0_WIDGETS
72 #include <libgnomevfs/gnome-vfs-mime-utils.h>
74 #include <libgnomevfs/gnome-vfs-mime.h>
76 #include "modest-maemo-utils.h"
79 #define DEFAULT_FONT_SIZE 3
80 #define DEFAULT_FONT 2
81 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
82 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
83 #define DEFAULT_MAIN_VBOX_SPACING 6
84 #define SUBJECT_MAX_LENGTH 1000
85 #define IMAGE_MAX_WIDTH 608
86 #define DEFAULT_FONT_SCALE 1.5
88 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
89 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
90 static void modest_msg_edit_window_finalize (GObject *obj);
92 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
93 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
94 static void send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
95 static void style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
96 static void setup_insensitive_handlers (ModestMsgEditWindow *editor);
97 static void reset_modified (ModestMsgEditWindow *editor);
99 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
100 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
101 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
102 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
103 GtkTextIter *start, GtkTextIter *end,
105 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
106 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
107 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
109 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
111 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
113 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
114 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
115 GdkEventWindowState *event,
117 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
118 ModestRecptEditor *editor);
119 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
120 ModestMsgEditWindow *window);
122 /* ModestWindow methods implementation */
123 static void modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom);
124 static gdouble modest_msg_edit_window_get_zoom (ModestWindow *window);
125 static gboolean modest_msg_edit_window_zoom_minus (ModestWindow *window);
126 static gboolean modest_msg_edit_window_zoom_plus (ModestWindow *window);
127 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
128 gboolean show_toolbar);
129 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
131 ModestMsgEditWindow *window);
132 static void update_window_title (ModestMsgEditWindow *window);
133 static void update_dimmed (ModestMsgEditWindow *window);
134 static void update_paste_dimming (ModestMsgEditWindow *window);
135 static void update_select_all_dimming (ModestMsgEditWindow *window);
136 static void update_zoom_dimming (ModestMsgEditWindow *window);
139 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
140 ModestMsgEditWindow *window);
141 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
142 ModestMsgEditWindow *window);
143 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
145 GtkTextIter *match_start,
146 GtkTextIter *match_end);
148 static void DEBUG_BUFFER (WPTextBuffer *buffer)
153 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
154 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
155 while (!gtk_text_iter_is_end (&iter)) {
156 GString *output = g_string_new ("");
157 GSList *toggled_tags;
160 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
161 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
162 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
163 GtkTextTag *tag = (GtkTextTag *) node->data;
165 g_object_get (G_OBJECT (tag), "name", &name, NULL);
166 output = g_string_append (output, name);
167 g_string_append (output, " ");
169 output = g_string_append (output, "] OPENED [ ");
170 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
171 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
172 GtkTextTag *tag = (GtkTextTag *) node->data;
174 g_object_get (G_OBJECT (tag), "name", &name, NULL);
175 output = g_string_append (output, name);
176 g_string_append (output, " ");
178 output = g_string_append (output, "]\n");
179 g_message ("%s", output->str);
180 g_string_free (output, TRUE);
181 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
183 g_message ("END BUFFER");
188 /* static gboolean */
189 /* on_key_pressed (GtkWidget *self, */
190 /* GdkEventKey *event, */
191 /* gpointer user_data); */
193 static void edit_menu_activated (GtkAction *action,
195 static void view_menu_activated (GtkAction *action,
198 /* list my signals */
205 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
206 struct _ModestMsgEditWindowPrivate {
208 GtkWidget *header_box;
210 ModestPairList *from_field_protos;
211 GtkWidget *from_field;
215 GtkWidget *bcc_field;
216 GtkWidget *subject_field;
217 GtkWidget *attachments_view;
218 GtkWidget *priority_icon;
219 GtkWidget *add_attachment_button;
221 GtkWidget *cc_caption;
222 GtkWidget *bcc_caption;
223 gboolean update_caption_visibility;
224 GtkWidget *attachments_caption;
226 GtkTextBuffer *text_buffer;
228 GtkWidget *font_size_toolitem;
229 GtkWidget *font_face_toolitem;
230 GtkWidget *font_color_button;
231 GSList *font_items_group;
232 GtkWidget *font_tool_button_label;
233 GSList *size_items_group;
234 GtkWidget *size_tool_button_label;
236 GtkWidget *find_toolbar;
240 GtkWidget *scroll_area;
245 TnyHeaderFlags priority_flags;
249 gulong clipboard_change_handler_id;
256 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
257 MODEST_TYPE_MSG_EDIT_WINDOW, \
258 ModestMsgEditWindowPrivate))
260 static GtkWindowClass *parent_class = NULL;
262 /* uncomment the following if you have defined any signals */
263 /* static guint signals[LAST_SIGNAL] = {0}; */
266 modest_msg_edit_window_get_type (void)
268 static GType my_type = 0;
270 static const GTypeInfo my_info = {
271 sizeof(ModestMsgEditWindowClass),
272 NULL, /* base init */
273 NULL, /* base finalize */
274 (GClassInitFunc) modest_msg_edit_window_class_init,
275 NULL, /* class finalize */
276 NULL, /* class data */
277 sizeof(ModestMsgEditWindow),
279 (GInstanceInitFunc) modest_msg_edit_window_init,
282 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
283 "ModestMsgEditWindow",
286 wp_text_buffer_library_init ();
292 save_state (ModestWindow *self)
294 modest_widget_memory_save (modest_runtime_get_conf(),
295 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
300 restore_settings (ModestMsgEditWindow *self)
302 modest_widget_memory_restore (modest_runtime_get_conf(),
303 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
308 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
310 GObjectClass *gobject_class;
311 ModestWindowClass *modest_window_class;
312 gobject_class = (GObjectClass*) klass;
313 modest_window_class = (ModestWindowClass*) klass;
315 parent_class = g_type_class_peek_parent (klass);
316 gobject_class->finalize = modest_msg_edit_window_finalize;
318 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
319 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
320 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
321 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
322 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
323 modest_window_class->save_state_func = save_state;
325 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
331 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
333 ModestMsgEditWindowPrivate *priv;
334 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
336 priv->msg_body = NULL;
337 priv->from_field = NULL;
338 priv->to_field = NULL;
339 priv->cc_field = NULL;
340 priv->bcc_field = NULL;
341 priv->subject_field = NULL;
342 priv->attachments = NULL;
344 priv->zoom_level = 1.0;
346 priv->cc_caption = NULL;
347 priv->bcc_caption = NULL;
348 priv->update_caption_visibility = FALSE;
350 priv->priority_flags = 0;
352 priv->find_toolbar = NULL;
353 priv->last_search = NULL;
355 priv->draft_msg = NULL;
356 priv->outbox_msg = NULL;
357 priv->clipboard_change_handler_id = 0;
362 /* FIXME: this is a dup from the one in gtk/ */
365 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
367 static ModestPairList*
368 get_transports (void)
370 GSList *transports = NULL;
372 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
373 GSList *accounts = modest_account_mgr_account_names (account_mgr,
374 TRUE /* only enabled accounts. */);
376 GSList *cursor = accounts;
378 gchar *account_name = cursor->data;
379 gchar *from_string = NULL;
381 from_string = modest_account_mgr_get_from_string (account_mgr,
385 if (from_string && account_name) {
386 gchar *name = account_name;
387 ModestPair *pair = modest_pair_new ((gpointer) name,
388 (gpointer) from_string , TRUE);
389 transports = g_slist_prepend (transports, pair);
392 cursor = cursor->next;
394 g_slist_free (accounts); /* only free the accounts, not the elements,
395 * because they are used in the pairlist */
401 init_window (ModestMsgEditWindow *obj)
403 GtkWidget *from_caption, *to_caption, *subject_caption;
404 GtkWidget *main_vbox;
405 ModestMsgEditWindowPrivate *priv;
407 GtkSizeGroup *size_group;
409 GtkWidget *subject_box;
410 GtkWidget *attachment_icon;
411 GtkWidget *window_box;
412 #if (GTK_MINOR_VERSION >= 10)
413 GdkAtom deserialize_type;
415 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
417 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
419 /* Note: This ModestPairList* must exist for as long as the combo
420 * that uses it, because the ModestComboBox uses the ID opaquely,
421 * so it can't know how to manage its memory. */
422 priv->from_field_protos = get_transports ();
424 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
426 priv->to_field = modest_recpt_editor_new ();
427 priv->cc_field = modest_recpt_editor_new ();
428 priv->bcc_field = modest_recpt_editor_new ();
429 subject_box = gtk_hbox_new (FALSE, 0);
430 priv->priority_icon = gtk_image_new ();
431 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
432 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
433 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
434 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
435 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
436 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
437 priv->add_attachment_button = gtk_button_new ();
438 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
439 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
440 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
441 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
442 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
443 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
444 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
445 priv->attachments_view = modest_attachments_view_new (NULL);
447 priv->header_box = gtk_vbox_new (FALSE, 0);
449 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
450 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
451 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
452 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
453 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
454 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
455 g_object_unref (size_group);
457 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
458 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
459 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
460 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
461 gtk_size_group_add_widget (size_group, priv->subject_field);
462 gtk_size_group_add_widget (size_group, priv->attachments_view);
463 g_object_unref (size_group);
465 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
466 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
467 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
468 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
469 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
470 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
471 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
474 priv->msg_body = wp_text_view_new ();
475 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
476 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
477 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
478 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
479 #if (GTK_MINOR_VERSION >= 10)
480 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
481 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
483 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
484 deserialize_type, TRUE);
486 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
488 priv->find_toolbar = hildon_find_toolbar_new (NULL);
489 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
491 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
493 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
494 G_CALLBACK (text_buffer_refresh_attributes), obj);
495 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
496 G_CALLBACK (text_buffer_can_undo), obj);
497 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
498 G_CALLBACK (text_buffer_can_redo), obj);
499 g_signal_connect (G_OBJECT (obj), "window-state-event",
500 G_CALLBACK (modest_msg_edit_window_window_state_event),
502 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
503 G_CALLBACK (text_buffer_apply_tag), obj);
504 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
505 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
506 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
507 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
508 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
509 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
511 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
512 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
514 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
515 G_CALLBACK (msg_body_focus), obj);
516 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
517 G_CALLBACK (msg_body_focus), obj);
518 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
519 "changed", G_CALLBACK (recpt_field_changed), obj);
520 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
521 "changed", G_CALLBACK (recpt_field_changed), obj);
522 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
523 "changed", G_CALLBACK (recpt_field_changed), obj);
524 recpt_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
525 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
527 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
528 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
530 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
531 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
532 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
533 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
535 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
537 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
538 frame = gtk_frame_new (NULL);
539 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
541 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
542 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
543 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
545 window_box = gtk_vbox_new (FALSE, 0);
546 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
547 gtk_container_add (GTK_CONTAINER(obj), window_box);
548 priv->scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
549 gtk_container_add (GTK_CONTAINER (frame), priv->scroll_area);
551 gtk_container_set_focus_vadjustment (GTK_CONTAINER (priv->scroll_area),
552 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
554 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
555 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
562 modest_msg_edit_window_finalize (GObject *obj)
564 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
566 if (priv->clipboard_change_handler_id > 0) {
567 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), priv->clipboard_change_handler_id);
568 priv->clipboard_change_handler_id = 0;
571 if (priv->draft_msg != NULL) {
572 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
573 if (TNY_IS_HEADER (header)) {
574 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
575 modest_window_mgr_unregister_header (mgr, header);
577 g_object_unref (priv->draft_msg);
578 priv->draft_msg = NULL;
580 if (priv->outbox_msg != NULL) {
581 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
582 if (TNY_IS_HEADER (header)) {
583 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
584 modest_window_mgr_unregister_header (mgr, header);
586 g_object_unref (priv->outbox_msg);
587 priv->outbox_msg = NULL;
590 /* This had to stay alive for as long as the combobox that used it: */
591 modest_pair_list_free (priv->from_field_protos);
593 G_OBJECT_CLASS(parent_class)->finalize (obj);
597 menubar_to_menu (GtkUIManager *ui_manager)
599 GtkWidget *main_menu;
603 /* Create new main menu */
604 main_menu = gtk_menu_new();
606 /* Get the menubar from the UI manager */
607 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
609 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
613 menu = GTK_WIDGET (iter->data);
614 gtk_widget_reparent(menu, main_menu);
616 iter = g_list_next (iter);
622 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type)
624 GdkPixbufLoader *loader;
627 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
632 tny_stream_reset (TNY_STREAM (stream));
633 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
634 unsigned char read_buffer[128];
636 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
637 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
641 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
642 g_object_ref (pixbuf);
643 gdk_pixbuf_loader_close (loader, NULL);
644 g_object_unref (loader);
646 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
647 GdkPixbuf *new_pixbuf;
649 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
650 gdk_pixbuf_get_width (pixbuf);
651 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
652 g_object_unref (pixbuf);
660 replace_with_attachments (ModestMsgEditWindow *self, GList *attachments)
662 ModestMsgEditWindowPrivate *priv;
665 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
667 for (node = attachments; node != NULL; node = g_list_next (node)) {
668 TnyMimePart *part = (TnyMimePart *) node->data;
669 const gchar *cid = tny_mime_part_get_content_id (part);
670 const gchar *mime_type = tny_mime_part_get_content_type (part);
671 if ((cid != NULL)&&(mime_type != NULL)) {
672 TnyStream *stream = tny_mime_part_get_stream (part);
673 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type);
674 g_object_unref (stream);
676 if (pixbuf != NULL) {
677 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
678 g_object_unref (pixbuf);
685 update_last_cid (ModestMsgEditWindow *self, GList *attachments)
688 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
690 for (node = attachments; node != NULL; node = g_list_next (node)) {
691 TnyMimePart *part = (TnyMimePart *) node->data;
692 const gchar *cid = tny_mime_part_get_content_id (part);
694 char *invalid = NULL;
695 gint int_cid = strtol (cid, &invalid, 10);
696 if ((invalid != NULL) && (*invalid == '\0') && (int_cid > priv->last_cid)) {
697 priv->last_cid = int_cid;
705 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
708 const gchar *to, *cc, *bcc, *subject;
710 ModestMsgEditWindowPrivate *priv;
712 TnyHeaderFlags priority_flags;
713 TnyFolder *msg_folder;
714 gboolean is_html = FALSE;
716 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
717 g_return_if_fail (TNY_IS_MSG (msg));
719 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
721 header = tny_msg_get_header (msg);
722 to = tny_header_get_to (header);
723 cc = tny_header_get_cc (header);
724 bcc = tny_header_get_bcc (header);
725 subject = tny_header_get_subject (header);
726 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
729 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
731 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
732 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
733 gtk_widget_show (priv->cc_caption);
734 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
735 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
736 gtk_widget_hide (priv->cc_caption);
739 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
740 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
741 gtk_widget_show (priv->bcc_caption);
742 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
743 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
744 gtk_widget_hide (priv->bcc_caption);
747 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
748 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
751 update_window_title (self);
753 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
754 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
756 if ((body == NULL)||(body[0] == '\0')) {
758 body = modest_text_utils_convert_to_html ("");
761 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
762 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
765 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
768 if (preserve_is_rich && !is_html) {
769 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
770 /* Get the default format required from configuration */
771 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
772 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
775 /* Set the default focus depending on having already a To: field or not */
776 if ((!to)||(*to == '\0')) {
777 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
779 gtk_widget_grab_focus (priv->msg_body);
782 /* TODO: lower priority, select in the From: combo to the
783 value that comes from msg <- not sure, should it be
786 /* Add attachments to the view */
787 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
788 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
789 if (priv->attachments == NULL) {
790 gtk_widget_hide (priv->attachments_caption);
792 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
793 gtk_widget_show_all (priv->attachments_caption);
794 replace_with_attachments (self, priv->attachments);
796 update_last_cid (self, priv->attachments);
798 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
800 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
801 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
803 reset_modified (self);
805 update_dimmed (self);
806 text_buffer_can_undo (priv->text_buffer, FALSE, self);
807 text_buffer_can_redo (priv->text_buffer, FALSE, self);
809 /* we should set a reference to the incoming message if it is a draft */
810 msg_folder = tny_msg_get_folder (msg);
812 if (modest_tny_folder_is_local_folder (msg_folder)) {
813 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
814 if (type == TNY_FOLDER_TYPE_DRAFTS)
815 priv->draft_msg = g_object_ref(msg);
816 if (type == TNY_FOLDER_TYPE_OUTBOX)
817 priv->outbox_msg = g_object_ref(msg);
819 g_object_unref (msg_folder);
824 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
827 GList *item_children, *node;
828 GtkWidget *bin_child;
830 bin_child = gtk_bin_get_child (GTK_BIN(item));
832 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
834 for (node = item_children; node != NULL; node = g_list_next (node)) {
835 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
836 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
839 g_list_free (item_children);
843 menu_tool_button_dont_expand (GtkMenuToolButton *item)
846 GList *item_children, *node;
848 box = gtk_bin_get_child (GTK_BIN (item));
849 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
850 item_children = gtk_container_get_children (GTK_CONTAINER (box));
852 for (node = item_children; node != NULL; node = g_list_next (node)) {
853 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
854 if (GTK_IS_TOGGLE_BUTTON (node->data))
855 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
856 else if (GTK_IS_BUTTON (node->data))
857 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
859 g_list_free (item_children);
864 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
866 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
867 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
868 GtkWidget *placeholder;
869 GtkWidget *tool_item;
874 GtkWidget *sizes_menu;
875 GtkWidget *fonts_menu;
876 GSList *radio_group = NULL;
881 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
882 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
884 /* should we hide the toolbar? */
885 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
886 gtk_widget_hide (parent_priv->toolbar);
888 /* Font color placeholder */
889 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
890 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
893 tool_item = GTK_WIDGET (gtk_tool_item_new ());
894 priv->font_color_button = hildon_color_button_new ();
895 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
896 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
897 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
898 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
899 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
900 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
901 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
903 /* Font size and face placeholder */
904 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
905 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
907 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
908 priv->size_tool_button_label = gtk_label_new (NULL);
909 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
910 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
911 size_text,"</span>", NULL);
912 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
914 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
915 sizes_menu = gtk_menu_new ();
916 priv->size_items_group = NULL;
918 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
919 GtkWidget *size_menu_item;
921 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
922 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
923 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
924 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
925 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
926 gtk_widget_show (size_menu_item);
928 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
932 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
933 GtkWidget *item = (GtkWidget *) node->data;
934 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
938 priv->size_items_group = g_slist_reverse (priv->size_items_group);
939 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
940 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
941 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
942 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
943 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
944 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
945 priv->font_size_toolitem = tool_item;
948 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
949 priv->font_tool_button_label = gtk_label_new (NULL);
950 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
951 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
953 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
954 fonts_menu = gtk_menu_new ();
955 priv->font_items_group = NULL;
957 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
958 GtkWidget *font_menu_item;
959 GtkWidget *child_label;
961 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
962 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
963 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
964 wp_get_font_name (font_index), "</span>", NULL);
965 gtk_label_set_markup (GTK_LABEL (child_label), markup);
968 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
969 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
970 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
971 gtk_widget_show (font_menu_item);
973 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
976 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
977 GtkWidget *item = (GtkWidget *) node->data;
978 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
981 priv->font_items_group = g_slist_reverse (priv->font_items_group);
982 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
983 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
984 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
985 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
986 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
987 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
988 priv->font_face_toolitem = tool_item;
990 /* Set expand and homogeneous for remaining items */
991 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
992 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
993 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
994 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
995 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
996 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
997 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
998 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
999 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1007 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1010 ModestWindowPrivate *parent_priv;
1011 ModestMsgEditWindowPrivate *priv;
1012 GtkActionGroup *action_group;
1013 GError *error = NULL;
1014 GdkPixbuf *window_icon = NULL;
1017 gboolean prefer_formatted;
1019 ModestPair *account_pair = NULL;
1021 g_return_val_if_fail (msg, NULL);
1022 g_return_val_if_fail (account_name, NULL);
1024 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
1026 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1027 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1029 parent_priv->ui_manager = gtk_ui_manager_new();
1030 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
1031 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1033 /* Add common actions */
1034 gtk_action_group_add_actions (action_group,
1035 modest_msg_edit_action_entries,
1036 G_N_ELEMENTS (modest_msg_edit_action_entries),
1038 gtk_action_group_add_toggle_actions (action_group,
1039 modest_msg_edit_toggle_action_entries,
1040 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
1042 gtk_action_group_add_radio_actions (action_group,
1043 modest_msg_edit_alignment_radio_action_entries,
1044 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
1046 G_CALLBACK (modest_ui_actions_on_change_justify),
1048 gtk_action_group_add_radio_actions (action_group,
1049 modest_msg_edit_zoom_action_entries,
1050 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
1052 G_CALLBACK (modest_ui_actions_on_change_zoom),
1054 gtk_action_group_add_radio_actions (action_group,
1055 modest_msg_edit_priority_action_entries,
1056 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
1058 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
1060 gtk_action_group_add_radio_actions (action_group,
1061 modest_msg_edit_file_format_action_entries,
1062 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
1063 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
1064 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
1066 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1067 g_object_unref (action_group);
1069 /* Load the UI definition */
1070 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
1072 if (error != NULL) {
1073 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
1074 g_clear_error (&error);
1077 /* Add accelerators */
1078 gtk_window_add_accel_group (GTK_WINDOW (obj),
1079 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1082 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
1083 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1086 init_window (MODEST_MSG_EDIT_WINDOW(obj));
1088 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1090 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1092 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1093 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1095 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
1097 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
1098 if (account_pair != NULL)
1099 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
1101 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1103 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1105 /* Set window icon */
1106 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
1108 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1109 g_object_unref (window_icon);
1112 /* Dim at start clipboard actions */
1113 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
1114 gtk_action_set_sensitive (action, FALSE);
1115 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
1116 gtk_action_set_sensitive (action, FALSE);
1117 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
1118 gtk_action_set_sensitive (action, FALSE);
1120 /* Update select all */
1121 update_select_all_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1122 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu");
1123 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (edit_menu_activated), obj);
1124 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu");
1125 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (view_menu_activated), obj);
1127 /* set initial state of cc and bcc */
1128 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
1129 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1130 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
1131 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
1132 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1133 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
1135 /* Setup the file format */
1136 conf = modest_runtime_get_conf ();
1137 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
1139 g_clear_error (&error);
1140 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
1142 file_format = (prefer_formatted) ?
1143 MODEST_FILE_FORMAT_FORMATTED_TEXT :
1144 MODEST_FILE_FORMAT_PLAIN_TEXT;
1145 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
1147 update_paste_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1148 priv->update_caption_visibility = TRUE;
1150 reset_modified (MODEST_MSG_EDIT_WINDOW (obj));
1152 return (ModestWindow*) obj;
1156 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1158 GString **string_buffer = (GString **) user_data;
1160 *string_buffer = g_string_append (*string_buffer, buffer);
1166 * @result: A new string which should be freed with g_free().
1169 get_formatted_data (ModestMsgEditWindow *edit_window)
1171 ModestMsgEditWindowPrivate *priv;
1172 GString *string_buffer = g_string_new ("");
1174 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1176 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1178 return g_string_free (string_buffer, FALSE);
1183 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1186 const gchar *account_name;
1187 ModestMsgEditWindowPrivate *priv;
1189 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1191 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1193 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1194 g_return_val_if_fail (account_name, NULL);
1197 /* don't free these (except from) */
1198 data = g_slice_new0 (MsgData);
1199 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1201 data->account_name = g_strdup (account_name);
1202 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1203 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1204 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1205 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1206 if (priv->draft_msg) {
1207 data->draft_msg = g_object_ref (priv->draft_msg);
1209 if (priv->outbox_msg) {
1210 data->draft_msg = g_object_ref (priv->outbox_msg);
1212 data->draft_msg = NULL;
1215 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1217 gtk_text_buffer_get_bounds (buf, &b, &e);
1218 data->plain_body = g_strdup (gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE)); /* returns a copy */
1220 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1221 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1223 data->html_body = NULL;
1225 /* deep-copy the data */
1226 GList *cursor = priv->attachments;
1227 data->attachments = NULL;
1229 if (!(TNY_IS_MIME_PART(cursor->data))) {
1230 g_warning ("strange data in attachment list");
1231 cursor = g_list_next (cursor);
1234 data->attachments = g_list_append (data->attachments,
1235 g_object_ref (cursor->data));
1236 cursor = g_list_next (cursor);
1239 data->priority_flags = priv->priority_flags;
1246 unref_gobject (GObject *obj, gpointer data)
1248 if (!G_IS_OBJECT(obj))
1250 g_object_unref (obj);
1254 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1257 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1265 g_free (data->subject);
1266 g_free (data->plain_body);
1267 g_free (data->html_body);
1268 g_free (data->account_name);
1270 if (data->draft_msg != NULL) {
1271 g_object_unref (data->draft_msg);
1272 data->draft_msg = NULL;
1275 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1276 g_list_free (data->attachments);
1278 g_slice_free (MsgData, data);
1282 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1285 ModestMsgEditWindowPrivate *priv = NULL;
1286 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1288 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1290 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1292 return MODEST_MSG_EDIT_FORMAT_HTML;
1294 return MODEST_MSG_EDIT_FORMAT_TEXT;
1298 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1299 ModestMsgEditFormat format)
1301 ModestMsgEditWindowPrivate *priv;
1303 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1304 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1307 case MODEST_MSG_EDIT_FORMAT_HTML:
1308 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1310 case MODEST_MSG_EDIT_FORMAT_TEXT:
1311 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1314 g_return_if_reached ();
1318 ModestMsgEditFormatState *
1319 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1321 ModestMsgEditFormatState *format_state = NULL;
1322 ModestMsgEditWindowPrivate *priv;
1323 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1325 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1326 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1328 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1330 format_state = g_new0 (ModestMsgEditFormatState, 1);
1331 format_state->bold = buffer_format->bold&0x1;
1332 format_state->italics = buffer_format->italic&0x1;
1333 format_state->bullet = buffer_format->bullet&0x1;
1334 format_state->color = buffer_format->color;
1335 format_state->font_size = buffer_format->font_size;
1336 format_state->font_family = wp_get_font_name (buffer_format->font);
1337 format_state->justification = buffer_format->justification;
1338 g_free (buffer_format);
1340 return format_state;
1345 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1346 const ModestMsgEditFormatState *format_state)
1348 ModestMsgEditWindowPrivate *priv;
1349 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1350 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1351 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1352 g_return_if_fail (format_state != NULL);
1354 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1355 gtk_widget_grab_focus (priv->msg_body);
1356 buffer_format->bold = (format_state->bold != FALSE);
1357 buffer_format->italic = (format_state->italics != FALSE);
1358 buffer_format->color = format_state->color;
1359 buffer_format->font_size = format_state->font_size;
1360 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1361 buffer_format->justification = format_state->justification;
1362 buffer_format->bullet = format_state->bullet;
1364 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1366 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1367 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1368 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1369 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1370 buffer_format->cs.font = (buffer_format->font != current_format->font);
1371 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1372 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1374 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1375 if (buffer_format->cs.bold) {
1376 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1378 if (buffer_format->cs.italic) {
1379 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1381 if (buffer_format->cs.color) {
1382 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1384 if (buffer_format->cs.font_size) {
1385 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1387 if (buffer_format->cs.justification) {
1388 switch (buffer_format->justification) {
1389 case GTK_JUSTIFY_LEFT:
1390 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1392 case GTK_JUSTIFY_CENTER:
1393 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1395 case GTK_JUSTIFY_RIGHT:
1396 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1403 if (buffer_format->cs.font) {
1404 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1406 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1407 if (buffer_format->cs.bullet) {
1408 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((buffer_format->bullet)?1:0));
1410 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1412 g_free (current_format);
1417 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1419 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1421 ModestWindowPrivate *parent_priv;
1422 ModestMsgEditWindowPrivate *priv;
1423 GtkWidget *new_size_menuitem;
1424 GtkWidget *new_font_menuitem;
1426 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1427 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1429 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1430 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1431 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1432 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1434 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1435 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1436 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1439 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1441 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1442 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1444 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1445 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1447 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1448 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1450 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1451 G_CALLBACK (modest_msg_edit_window_color_button_change),
1453 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1454 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1455 G_CALLBACK (modest_msg_edit_window_color_button_change),
1458 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1459 buffer_format->font_size))->data);
1460 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1464 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1465 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1466 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1468 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1469 G_CALLBACK (modest_msg_edit_window_size_change),
1471 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1472 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1473 G_CALLBACK (modest_msg_edit_window_size_change),
1477 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1478 buffer_format->font))->data);
1479 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1483 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1484 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1485 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1487 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1488 G_CALLBACK (modest_msg_edit_window_font_change),
1490 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1491 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1492 G_CALLBACK (modest_msg_edit_window_font_change),
1496 g_free (buffer_format);
1502 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1505 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1506 ModestMsgEditWindowPrivate *priv;
1507 GtkWidget *dialog = NULL;
1509 const GdkColor *new_color = NULL;
1511 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1512 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1514 #ifdef MODEST_HILDON_VERSION_0
1515 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1516 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1518 dialog = hildon_color_chooser_new ();
1519 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1520 #endif /*MODEST_HILDON_VERSION_0*/
1521 g_free (buffer_format);
1523 response = gtk_dialog_run (GTK_DIALOG (dialog));
1525 case GTK_RESPONSE_OK: {
1526 #ifdef MODEST_HILDON_VERSION_0
1527 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1530 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1532 #endif /*MODEST_HILDON_VERSION_0*/
1539 gtk_widget_destroy (dialog);
1541 if (new_color != NULL)
1542 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1547 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1550 ModestMsgEditWindowPrivate *priv;
1551 GtkWidget *dialog = NULL;
1553 GdkColor *old_color = NULL;
1554 const GdkColor *new_color = NULL;
1556 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1557 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1559 #ifdef MODEST_HILDON_VERSION_0
1560 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1561 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1563 dialog = hildon_color_chooser_new ();
1564 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1565 #endif /*MODEST_HILDON_VERSION_9*/
1567 response = gtk_dialog_run (GTK_DIALOG (dialog));
1569 case GTK_RESPONSE_OK: {
1570 #ifdef MODEST_HILDON_VERSION_0
1571 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1574 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1576 #endif /*MODEST_HILDON_VERSION_0*/
1582 gtk_widget_destroy (dialog);
1584 if (new_color != NULL)
1585 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1589 static TnyStream* create_stream_for_uri (const gchar* uri)
1594 TnyStream *result = NULL;
1596 GnomeVFSHandle *handle = NULL;
1597 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1598 if (test == GNOME_VFS_OK) {
1599 /* Create the tinymail stream: */
1600 /* Presumably tinymai will call gnome_vfs_close (handle) later. */
1601 result = TNY_STREAM (tny_vfs_stream_new (handle));
1608 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1611 ModestMsgEditWindowPrivate *priv;
1612 GtkWidget *dialog = NULL;
1614 GSList *uris = NULL;
1615 GSList *uri_node = NULL;
1617 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1619 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1620 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1621 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1623 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1625 response = gtk_dialog_run (GTK_DIALOG (dialog));
1627 case GTK_RESPONSE_OK:
1628 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1633 gtk_widget_destroy (dialog);
1635 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1637 GnomeVFSHandle *handle = NULL;
1638 GnomeVFSResult result;
1639 GtkTextIter position;
1640 GtkTextMark *insert_mark;
1642 uri = (const gchar *) uri_node->data;
1643 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1644 if (result == GNOME_VFS_OK) {
1646 GnomeVFSFileInfo info;
1647 gchar *filename, *basename, *escaped_filename;
1648 TnyMimePart *mime_part;
1650 const gchar *mime_type = NULL;
1651 GnomeVFSURI *vfs_uri;
1653 vfs_uri = gnome_vfs_uri_new (uri);
1655 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1656 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1657 g_free (escaped_filename);
1658 gnome_vfs_uri_unref (vfs_uri);
1660 if (gnome_vfs_get_file_info (uri, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
1661 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1663 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1665 mime_part = tny_platform_factory_new_mime_part
1666 (modest_runtime_get_platform_factory ());
1668 TnyStream *stream = create_stream_for_uri (uri);
1669 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1671 content_id = g_strdup_printf ("%d", priv->last_cid);
1672 tny_mime_part_set_content_id (mime_part, content_id);
1673 g_free (content_id);
1676 basename = g_path_get_basename (filename);
1677 tny_mime_part_set_filename (mime_part, basename);
1680 pixbuf = pixbuf_from_stream (stream, mime_type);
1682 if (pixbuf != NULL) {
1683 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1684 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1685 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1688 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1689 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1691 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1692 gtk_widget_show_all (priv->attachments_caption);
1693 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1703 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
1706 ModestMsgEditWindowPrivate *priv;
1707 GtkWidget *dialog = NULL;
1709 GSList *uris = NULL;
1712 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1714 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1715 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
1716 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1718 response = gtk_dialog_run (GTK_DIALOG (dialog));
1720 case GTK_RESPONSE_OK:
1721 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1726 gtk_widget_destroy (dialog);
1728 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1729 const gchar *uri = (const gchar *) uri_node->data;
1730 modest_msg_edit_window_attach_file_one (window, uri);
1732 g_slist_foreach (uris, (GFunc) g_free, NULL);
1733 g_slist_free (uris);
1737 modest_msg_edit_window_attach_file_one (
1738 ModestMsgEditWindow *window,
1741 g_return_if_fail (window);
1742 g_return_if_fail (uri);
1744 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1747 GnomeVFSHandle *handle = NULL;
1748 GnomeVFSResult result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1749 if (result == GNOME_VFS_OK) {
1750 TnyMimePart *mime_part;
1752 const gchar *mime_type = NULL;
1754 gchar *escaped_filename;
1757 GnomeVFSFileInfo info;
1758 GnomeVFSURI *vfs_uri;
1760 vfs_uri = gnome_vfs_uri_new (uri);
1763 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1764 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1765 g_free (escaped_filename);
1766 gnome_vfs_uri_unref (vfs_uri);
1768 if (gnome_vfs_get_file_info (uri,
1770 GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
1771 GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1773 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1774 mime_part = tny_platform_factory_new_mime_part
1775 (modest_runtime_get_platform_factory ());
1776 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1778 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1780 content_id = g_strdup_printf ("%d", priv->last_cid);
1781 tny_mime_part_set_content_id (mime_part, content_id);
1782 g_free (content_id);
1785 basename = g_path_get_basename (filename);
1786 tny_mime_part_set_filename (mime_part, basename);
1789 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1790 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1792 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1793 gtk_widget_show_all (priv->attachments_caption);
1794 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1800 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1803 ModestMsgEditWindowPrivate *priv;
1804 gboolean clean_list = FALSE;
1806 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1807 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1809 if (att_list == NULL) {
1810 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1814 if (att_list == NULL) {
1815 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1817 GtkWidget *confirmation_dialog = NULL;
1818 gboolean dialog_response;
1820 gchar *message = NULL;
1821 const gchar *filename = NULL;
1823 if (att_list->next == NULL) {
1824 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1828 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1829 att_list->next == NULL), filename);
1830 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1832 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1833 gtk_widget_destroy (confirmation_dialog);
1834 if (!dialog_response) {
1836 g_list_free (att_list);
1839 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1841 for (node = att_list; node != NULL; node = g_list_next (node)) {
1842 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1843 const gchar *att_id;
1844 priv->attachments = g_list_remove (priv->attachments, mime_part);
1846 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1848 if (priv->attachments == NULL)
1849 gtk_widget_hide (priv->attachments_caption);
1850 att_id = tny_mime_part_get_content_id (mime_part);
1852 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1854 g_object_unref (mime_part);
1855 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1860 g_list_free (att_list);
1864 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1867 ModestMsgEditWindowPrivate *priv;
1868 GdkColor *new_color;
1869 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1871 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1872 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1875 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1877 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1879 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1881 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1886 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1889 ModestMsgEditWindowPrivate *priv;
1890 gint new_size_index;
1891 ModestMsgEditWindow *window;
1894 window = MODEST_MSG_EDIT_WINDOW (userdata);
1895 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1896 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1898 if (gtk_check_menu_item_get_active (menu_item)) {
1900 WPTextBufferFormat format;
1902 memset (&format, 0, sizeof (format));
1903 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1905 label = gtk_bin_get_child (GTK_BIN (menu_item));
1907 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1908 format.cs.font_size = TRUE;
1909 format.cs.text_position = TRUE;
1910 format.cs.font = TRUE;
1911 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1912 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1914 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1915 (gpointer) wp_get_font_size_index (new_size_index, 12)))
1916 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1918 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1919 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1920 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1926 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1929 ModestMsgEditWindowPrivate *priv;
1930 gint new_font_index;
1931 ModestMsgEditWindow *window;
1934 window = MODEST_MSG_EDIT_WINDOW (userdata);
1935 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1936 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1938 if (gtk_check_menu_item_get_active (menu_item)) {
1941 label = gtk_bin_get_child (GTK_BIN (menu_item));
1943 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1945 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1946 (gpointer) new_font_index))
1947 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1949 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1950 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1951 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1957 modest_msg_edit_window_set_zoom (ModestWindow *window,
1960 ModestMsgEditWindowPrivate *priv;
1961 ModestWindowPrivate *parent_priv;
1962 GtkRadioAction *zoom_radio_action;
1964 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1966 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1967 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1968 priv->zoom_level = zoom;
1969 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom*DEFAULT_FONT_SCALE);
1971 /* Zoom level menu options should be updated with the current zoom level */
1972 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1973 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1974 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1975 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1976 /* FIXME: Not availible before Gtk 2.10 */
1978 gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
1983 modest_msg_edit_window_get_zoom (ModestWindow *window)
1985 ModestMsgEditWindowPrivate *priv;
1987 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1989 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1990 return priv->zoom_level;
1994 zoom_allowed (ModestMsgEditWindow *window)
1998 focus = gtk_window_get_focus (GTK_WINDOW (window));
1999 return (focus != NULL && WP_IS_TEXT_VIEW (focus));
2003 modest_msg_edit_window_zoom_plus (ModestWindow *window)
2005 ModestWindowPrivate *parent_priv;
2006 GtkRadioAction *zoom_radio_action;
2007 GSList *group, *node;
2009 /* First we check if the text view is focused. If not, zooming is not allowed */
2010 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2011 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2015 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2016 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2017 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2019 group = gtk_radio_action_get_group (zoom_radio_action);
2021 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
2022 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
2026 for (node = group; node != NULL; node = g_slist_next (node)) {
2027 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
2028 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
2036 modest_msg_edit_window_zoom_minus (ModestWindow *window)
2038 ModestWindowPrivate *parent_priv;
2039 GtkRadioAction *zoom_radio_action;
2040 GSList *group, *node;
2042 /* First we check if the text view is focused. If not, zooming is not allowed */
2043 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2044 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2048 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2049 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2050 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2052 group = gtk_radio_action_get_group (zoom_radio_action);
2054 for (node = group; node != NULL; node = g_slist_next (node)) {
2055 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
2056 if (node->next != NULL) {
2057 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
2060 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
2068 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2070 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2071 ModestWindowPrivate *parent_priv;
2072 ModestWindowMgr *mgr;
2073 gboolean is_fullscreen;
2074 GtkAction *fs_toggle_action;
2077 mgr = modest_runtime_get_window_mgr ();
2078 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2080 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2082 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2083 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2084 if (is_fullscreen != active)
2085 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2093 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
2095 ModestWindowPrivate *parent_priv;
2096 GtkAction *fs_toggle_action;
2099 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2101 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2102 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
2103 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
2107 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2110 ModestMsgEditWindowPrivate *priv = NULL;
2111 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2113 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2114 if (!priv->update_caption_visibility)
2117 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2119 gtk_widget_show (priv->cc_caption);
2121 gtk_widget_hide (priv->cc_caption);
2123 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2127 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2130 ModestMsgEditWindowPrivate *priv = NULL;
2131 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2133 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2134 if (!priv->update_caption_visibility)
2137 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2139 gtk_widget_show (priv->bcc_caption);
2141 gtk_widget_hide (priv->bcc_caption);
2143 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2147 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2148 ModestRecptEditor *editor)
2150 ModestMsgEditWindowPrivate *priv;
2152 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2153 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2154 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2156 if (editor == NULL) {
2157 GtkWidget *view_focus;
2158 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2160 /* This code should be kept in sync with ModestRecptEditor. The
2161 textview inside the recpt editor is the one that really gets the
2162 focus. As it's inside a scrolled window, and this one inside the
2163 hbox recpt editor inherits from, we'll need to go up in the
2164 hierarchy to know if the text view is part of the recpt editor
2165 or if it's a different text entry */
2167 if (gtk_widget_get_parent (view_focus)) {
2168 GtkWidget *first_parent;
2170 first_parent = gtk_widget_get_parent (view_focus);
2171 if (gtk_widget_get_parent (first_parent) &&
2172 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2173 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2178 editor = MODEST_RECPT_EDITOR (priv->to_field);
2182 modest_address_book_select_addresses (editor);
2187 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2189 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2191 modest_msg_edit_window_open_addressbook (window, NULL);
2195 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2196 gboolean show_toolbar)
2198 ModestWindowPrivate *parent_priv;
2200 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2201 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2203 /* FIXME: we can not just use the code of
2204 modest_msg_edit_window_setup_toolbar because it has a
2205 mixture of both initialization and creation code. */
2208 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2210 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2214 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2215 TnyHeaderFlags priority_flags)
2217 ModestMsgEditWindowPrivate *priv;
2218 ModestWindowPrivate *parent_priv;
2220 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2222 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2223 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2224 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2226 if (priv->priority_flags != priority_flags) {
2227 GtkAction *priority_action = NULL;
2229 priv->priority_flags = priority_flags;
2231 switch (priority_flags) {
2232 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2233 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2234 gtk_widget_show (priv->priority_icon);
2235 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2236 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2238 case TNY_HEADER_FLAG_LOW_PRIORITY:
2239 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2240 gtk_widget_show (priv->priority_icon);
2241 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2242 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2245 gtk_widget_hide (priv->priority_icon);
2246 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2247 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2250 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2251 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2256 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2259 ModestMsgEditWindowPrivate *priv;
2260 ModestWindowPrivate *parent_priv;
2261 gint current_format;
2263 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2265 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2266 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2268 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2269 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2271 if (current_format != file_format) {
2272 switch (file_format) {
2273 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2274 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2276 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2280 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2281 response = gtk_dialog_run (GTK_DIALOG (dialog));
2282 gtk_widget_destroy (dialog);
2283 if (response == GTK_RESPONSE_OK) {
2284 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2286 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2287 modest_maemo_toggle_action_set_active_block_notify (action, TRUE);
2292 update_dimmed (window);
2297 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2300 ModestMsgEditWindowPrivate *priv;
2301 WPTextBufferFormat oldfmt, fmt;
2302 gint old_position = 0;
2306 GdkColor *color = NULL;
2307 gboolean bold, bold_set, italic, italic_set;
2308 gboolean underline, underline_set;
2309 gboolean strikethrough, strikethrough_set;
2310 gboolean position_set;
2311 gboolean font_size_set, font_set, color_set;
2314 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2315 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2317 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2319 /* First we get the currently selected font information */
2320 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2321 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2323 switch (oldfmt.text_position) {
2324 case TEXT_POSITION_NORMAL:
2327 case TEXT_POSITION_SUPERSCRIPT:
2335 g_object_set (G_OBJECT (dialog),
2336 "bold", oldfmt.bold != FALSE,
2337 "bold-set", !oldfmt.cs.bold,
2338 "underline", oldfmt.underline != FALSE,
2339 "underline-set", !oldfmt.cs.underline,
2340 "italic", oldfmt.italic != FALSE,
2341 "italic-set", !oldfmt.cs.italic,
2342 "strikethrough", oldfmt.strikethrough != FALSE,
2343 "strikethrough-set", !oldfmt.cs.strikethrough,
2344 "color", &oldfmt.color,
2345 "color-set", !oldfmt.cs.color,
2346 "size", wp_font_size[oldfmt.font_size],
2347 "size-set", !oldfmt.cs.font_size,
2348 "position", old_position,
2349 "position-set", !oldfmt.cs.text_position,
2350 "family", wp_get_font_name (oldfmt.font),
2351 "family-set", !oldfmt.cs.font,
2354 gtk_widget_show_all (dialog);
2355 response = gtk_dialog_run (GTK_DIALOG (dialog));
2356 if (response == GTK_RESPONSE_OK) {
2358 g_object_get( dialog,
2360 "bold-set", &bold_set,
2361 "underline", &underline,
2362 "underline-set", &underline_set,
2364 "italic-set", &italic_set,
2365 "strikethrough", &strikethrough,
2366 "strikethrough-set", &strikethrough_set,
2368 "color-set", &color_set,
2370 "size-set", &font_size_set,
2371 "family", &font_name,
2372 "family-set", &font_set,
2373 "position", &position,
2374 "position-set", &position_set,
2379 if (response == GTK_RESPONSE_OK) {
2380 memset(&fmt, 0, sizeof(fmt));
2386 fmt.italic = italic;
2387 fmt.cs.italic = TRUE;
2389 if (underline_set) {
2390 fmt.underline = underline;
2391 fmt.cs.underline = TRUE;
2393 if (strikethrough_set) {
2394 fmt.strikethrough = strikethrough;
2395 fmt.cs.strikethrough = TRUE;
2400 ? TEXT_POSITION_NORMAL
2401 : ( ( position == 1 )
2402 ? TEXT_POSITION_SUPERSCRIPT
2403 : TEXT_POSITION_SUBSCRIPT );
2404 fmt.cs.text_position = TRUE;
2408 fmt.cs.color = TRUE;
2411 fmt.font = wp_get_font_index(font_name,
2416 if (font_size_set) {
2417 fmt.font_size = wp_get_font_size_index(
2418 font_size, DEFAULT_FONT_SIZE);
2419 fmt.cs.font_size = TRUE;
2421 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2423 gtk_widget_destroy (dialog);
2425 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2429 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2431 ModestMsgEditWindowPrivate *priv;
2433 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2434 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2436 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2438 update_dimmed (window);
2443 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2445 ModestMsgEditWindowPrivate *priv;
2447 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2448 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2450 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2452 update_dimmed (window);
2457 update_dimmed (ModestMsgEditWindow *window)
2459 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2460 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2464 gboolean editor_focused;
2466 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2467 editor_focused = gtk_widget_is_focus (priv->msg_body);
2469 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2470 gtk_action_set_sensitive (action, rich_text && editor_focused);
2471 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2472 gtk_action_set_sensitive (action, rich_text && editor_focused);
2473 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2474 gtk_action_set_sensitive (action, rich_text && editor_focused);
2475 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2476 gtk_action_set_sensitive (action, rich_text && editor_focused);
2477 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2478 gtk_action_set_sensitive (action, rich_text && editor_focused);
2479 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2480 gtk_action_set_sensitive (action, rich_text && editor_focused);
2481 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2482 gtk_action_set_sensitive (action, rich_text && editor_focused);
2483 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2484 gtk_action_set_sensitive (action, rich_text && editor_focused);
2485 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2486 gtk_action_set_sensitive (action, rich_text && editor_focused);
2487 widget = priv->font_color_button;
2488 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2489 widget = priv->font_size_toolitem;
2490 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2491 widget = priv->font_face_toolitem;
2492 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2496 setup_insensitive_handlers (ModestMsgEditWindow *window)
2498 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2499 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2502 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2503 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2504 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2505 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2506 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2507 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2508 widget = priv->font_color_button;
2509 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2510 widget = priv->font_size_toolitem;
2511 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2512 widget = priv->font_face_toolitem;
2513 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2518 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2520 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2523 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2524 gtk_action_set_sensitive (action, can_undo);
2528 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2530 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2533 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/RedoMenu");
2534 gtk_action_set_sensitive (action, can_redo);
2538 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2541 GtkTextIter match_start, match_end;
2543 if (image_id == NULL)
2546 gtk_text_buffer_get_start_iter (buffer, &iter);
2548 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2549 GSList *tags = gtk_text_iter_get_tags (&match_start);
2551 for (node = tags; node != NULL; node = g_slist_next (node)) {
2552 GtkTextTag *tag = (GtkTextTag *) node->data;
2553 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2554 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2555 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2557 offset = gtk_text_iter_get_offset (&match_start);
2558 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2559 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2563 gtk_text_iter_forward_char (&iter);
2568 msg_body_focus (GtkWidget *focus,
2569 GdkEventFocus *event,
2573 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2578 recpt_field_changed (GtkTextBuffer *buffer,
2579 ModestMsgEditWindow *editor)
2581 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2582 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2583 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2584 gboolean dim = FALSE;
2587 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2588 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2589 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2591 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2592 gtk_text_buffer_get_char_count (cc_buffer) +
2593 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2595 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2596 gtk_action_set_sensitive (action, !dim);
2597 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2598 gtk_action_set_sensitive (action, !dim);
2602 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2604 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2608 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2610 gboolean rich_text, editor_focused;
2612 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2613 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2614 editor_focused = gtk_widget_is_focus (priv->msg_body);
2617 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2618 else if (!editor_focused)
2619 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2623 reset_modified (ModestMsgEditWindow *editor)
2625 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2626 GtkTextBuffer *buffer;
2628 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2629 gtk_text_buffer_set_modified (buffer, FALSE);
2630 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2631 gtk_text_buffer_set_modified (buffer, FALSE);
2632 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2633 gtk_text_buffer_set_modified (buffer, FALSE);
2634 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2638 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2640 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2641 GtkTextBuffer *buffer;
2643 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2644 if (gtk_text_buffer_get_modified (buffer))
2646 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2647 if (gtk_text_buffer_get_modified (buffer))
2649 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2650 if (gtk_text_buffer_get_modified (buffer))
2652 if (gtk_text_buffer_get_modified (priv->text_buffer))
2659 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
2661 ModestMsgEditWindowPrivate *priv = NULL;
2663 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2664 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2666 /* check if there's no recipient added */
2667 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2668 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2669 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2670 /* no recipient contents, then select contacts */
2671 modest_msg_edit_window_open_addressbook (window, NULL);
2675 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook))
2677 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook))
2679 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook))
2682 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2689 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2690 ModestMsgEditWindow *window)
2692 modest_msg_edit_window_offer_attach_file (window);
2696 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2698 ModestMsgEditWindow *window)
2700 ModestWindowPrivate *parent_priv;
2701 ModestMsgEditWindowPrivate *priv;
2703 gboolean has_selection;
2705 GList *selected_attachments = NULL;
2706 gint n_att_selected = 0;
2708 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2709 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2711 if (!GTK_WIDGET_VISIBLE (window))
2713 has_selection = gtk_clipboard_wait_for_targets (clipboard, NULL, NULL);
2714 focused = gtk_window_get_focus (GTK_WINDOW (window));
2716 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2717 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2718 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2719 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2721 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2722 n_att_selected = g_list_length (selected_attachments);
2723 g_list_free (selected_attachments);
2725 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2726 gtk_action_set_sensitive (action, n_att_selected == 1);
2728 update_paste_dimming (window);
2732 update_window_title (ModestMsgEditWindow *window)
2734 ModestMsgEditWindowPrivate *priv = NULL;
2735 const gchar *subject;
2737 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2738 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2739 if (subject == NULL || subject[0] == '\0')
2740 subject = _("mail_va_new_email");
2742 gtk_window_set_title (GTK_WINDOW (window), subject);
2747 subject_field_changed (GtkEditable *editable,
2748 ModestMsgEditWindow *window)
2750 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2751 update_window_title (window);
2752 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2756 message_is_empty (ModestMsgEditWindow *window)
2758 ModestMsgEditWindowPrivate *priv = NULL;
2760 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2761 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2763 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
2764 * so we can ignore markup.
2766 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
2769 count = gtk_text_buffer_get_char_count (buf);
2775 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2778 ModestMsgEditWindowPrivate *priv = NULL;
2780 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2781 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2783 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2786 gtk_widget_show_all (priv->find_toolbar);
2787 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2789 gtk_widget_hide_all (priv->find_toolbar);
2790 gtk_widget_grab_focus (priv->msg_body);
2796 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2798 GtkTextIter *match_start,
2799 GtkTextIter *match_end)
2801 GtkTextIter end_iter;
2802 gchar *str_casefold;
2805 gchar *range_casefold;
2808 gboolean result = FALSE;
2815 gtk_text_iter_forward_to_end (&end_iter);
2817 str_casefold = g_utf8_casefold (str, -1);
2818 str_chars_n = strlen (str);
2820 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2821 range_casefold = g_utf8_casefold (range_text, -1);
2822 range_chars_n = strlen (range_casefold);
2824 if (range_chars_n < str_chars_n) {
2825 g_free (str_casefold);
2826 g_free (range_text);
2827 g_free (range_casefold);
2831 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2832 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2833 if (!g_utf8_collate (range_subtext, str_casefold)) {
2834 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2836 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2837 match_start, match_end, NULL);
2838 g_free (found_text);
2840 g_free (range_subtext);
2844 g_free (str_casefold);
2845 g_free (range_text);
2846 g_free (range_casefold);
2853 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2854 ModestMsgEditWindow *window)
2856 gchar *current_search = NULL;
2857 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2859 GtkTextIter selection_start, selection_end;
2860 GtkTextIter match_start, match_end;
2861 gboolean continue_search = FALSE;
2863 if (message_is_empty (window)) {
2864 g_free (priv->last_search);
2865 priv->last_search = NULL;
2866 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
2870 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2871 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2872 g_free (current_search);
2873 g_free (priv->last_search);
2874 priv->last_search = NULL;
2875 /* Information banner about empty search */
2876 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2880 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2881 continue_search = TRUE;
2883 g_free (priv->last_search);
2884 priv->last_search = g_strdup (current_search);
2887 if (continue_search) {
2888 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2889 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2890 &match_start, &match_end);
2892 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2894 GtkTextIter buffer_start;
2895 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2896 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2897 &match_start, &match_end);
2899 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2902 /* Mark as selected the string found in search */
2904 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2905 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2907 g_free (priv->last_search);
2908 priv->last_search = NULL;
2910 g_free (current_search);
2914 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2915 ModestMsgEditWindow *window)
2917 GtkToggleAction *toggle;
2918 ModestWindowPrivate *parent_priv;
2919 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2921 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2922 gtk_toggle_action_set_active (toggle, FALSE);
2927 update_paste_dimming (ModestMsgEditWindow *window)
2929 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2930 GtkAction *action = NULL;
2931 GtkClipboard *clipboard = NULL;
2932 ModestEmailClipboard *e_clipboard;
2936 focused = gtk_window_get_focus (GTK_WINDOW (window));
2938 e_clipboard = modest_runtime_get_email_clipboard ();
2939 if (!modest_email_clipboard_cleared (e_clipboard)) {
2942 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2943 active = gtk_clipboard_wait_is_text_available (clipboard);
2947 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2951 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2952 gtk_action_set_sensitive (action, active);
2957 update_select_all_dimming (ModestMsgEditWindow *window)
2960 gboolean dimmed = FALSE;
2962 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2964 focused = gtk_window_get_focus (GTK_WINDOW (window));
2965 if (GTK_IS_ENTRY (focused)) {
2966 const gchar *current_text;
2967 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
2968 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
2969 } else if (GTK_IS_TEXT_VIEW (focused)) {
2970 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
2971 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
2972 } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
2975 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
2976 gtk_action_set_sensitive (action, !dimmed);
2980 update_zoom_dimming (ModestMsgEditWindow *window)
2983 gboolean dimmed = FALSE;
2985 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2987 focused = gtk_window_get_focus (GTK_WINDOW (window));
2988 dimmed = ! WP_IS_TEXT_VIEW (focused);
2989 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2990 gtk_action_set_sensitive (action, !dimmed);
2994 edit_menu_activated (GtkAction *action,
2997 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2999 update_select_all_dimming (window);
3000 update_paste_dimming (window);
3003 view_menu_activated (GtkAction *action,
3006 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3008 update_zoom_dimming (window);
3012 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3014 ModestMsgEditWindowPrivate *priv;
3016 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3021 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3024 ModestMsgEditWindowPrivate *priv;
3026 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3032 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3035 ModestMsgEditWindowPrivate *priv;
3036 TnyHeader *header = NULL;
3038 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3039 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3041 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3042 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3044 if (priv->draft_msg != NULL) {
3045 header = tny_msg_get_header (priv->draft_msg);
3046 if (TNY_IS_HEADER (header)) {
3047 modest_window_mgr_unregister_header (mgr, header);
3049 g_object_unref (priv->draft_msg);
3052 if (draft != NULL) {
3053 g_object_ref (draft);
3054 header = tny_msg_get_header (draft);
3055 if (TNY_IS_HEADER (header))
3056 modest_window_mgr_register_header (mgr, header);
3059 priv->draft_msg = draft;
3063 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3064 GtkTextIter *start, GtkTextIter *end,
3067 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3068 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3071 if (tag == NULL+13) return;
3072 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3073 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3074 replace_with_attachments (window, priv->attachments);
3079 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3082 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3084 g_return_if_fail (TNY_IS_MIME_PART (part));
3085 priv->attachments = g_list_prepend (priv->attachments, part);
3086 g_object_ref (part);
3087 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part);
3088 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3089 gtk_widget_show_all (priv->attachments_caption);
3090 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);