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)
708 const gchar *to, *cc, *bcc, *subject;
710 ModestMsgEditWindowPrivate *priv;
712 TnyHeaderFlags priority_flags;
713 TnyFolder *msg_folder;
715 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
716 g_return_if_fail (TNY_IS_MSG (msg));
718 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
720 header = tny_msg_get_header (msg);
721 to = tny_header_get_to (header);
722 cc = tny_header_get_cc (header);
723 bcc = tny_header_get_bcc (header);
724 subject = tny_header_get_subject (header);
725 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
728 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
730 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
731 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
732 gtk_widget_show (priv->cc_caption);
733 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
734 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
735 gtk_widget_hide (priv->cc_caption);
738 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
739 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
740 gtk_widget_show (priv->bcc_caption);
741 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
742 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
743 gtk_widget_hide (priv->bcc_caption);
746 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
747 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
750 update_window_title (self);
752 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
753 body = modest_tny_msg_get_body (msg, TRUE);
755 if ((body == NULL)||(body[0] == '\0')) {
757 body = modest_text_utils_convert_to_html ("");
759 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
760 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
763 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
766 /* Get the default format required from configuration */
767 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
768 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
771 /* Set the default focus depending on having already a To: field or not */
772 if ((!to)||(*to == '\0')) {
773 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
775 gtk_widget_grab_focus (priv->msg_body);
778 /* TODO: lower priority, select in the From: combo to the
779 value that comes from msg <- not sure, should it be
782 /* Add attachments to the view */
783 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
784 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
785 if (priv->attachments == NULL) {
786 gtk_widget_hide (priv->attachments_caption);
788 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
789 gtk_widget_show_all (priv->attachments_caption);
790 replace_with_attachments (self, priv->attachments);
792 update_last_cid (self, priv->attachments);
794 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
796 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
797 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
799 reset_modified (self);
801 update_dimmed (self);
802 text_buffer_can_undo (priv->text_buffer, FALSE, self);
803 text_buffer_can_redo (priv->text_buffer, FALSE, self);
805 /* we should set a reference to the incoming message if it is a draft */
806 msg_folder = tny_msg_get_folder (msg);
808 if (modest_tny_folder_is_local_folder (msg_folder)) {
809 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
810 if (type == TNY_FOLDER_TYPE_DRAFTS)
811 priv->draft_msg = g_object_ref(msg);
812 if (type == TNY_FOLDER_TYPE_OUTBOX)
813 priv->outbox_msg = g_object_ref(msg);
815 g_object_unref (msg_folder);
820 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
823 GList *item_children, *node;
824 GtkWidget *bin_child;
826 bin_child = gtk_bin_get_child (GTK_BIN(item));
828 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
830 for (node = item_children; node != NULL; node = g_list_next (node)) {
831 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
832 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
835 g_list_free (item_children);
839 menu_tool_button_dont_expand (GtkMenuToolButton *item)
842 GList *item_children, *node;
844 box = gtk_bin_get_child (GTK_BIN (item));
845 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
846 item_children = gtk_container_get_children (GTK_CONTAINER (box));
848 for (node = item_children; node != NULL; node = g_list_next (node)) {
849 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
850 if (GTK_IS_TOGGLE_BUTTON (node->data))
851 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
852 else if (GTK_IS_BUTTON (node->data))
853 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
855 g_list_free (item_children);
860 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
862 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
863 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
864 GtkWidget *placeholder;
865 GtkWidget *tool_item;
870 GtkWidget *sizes_menu;
871 GtkWidget *fonts_menu;
872 GSList *radio_group = NULL;
877 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
878 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
880 /* should we hide the toolbar? */
881 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
882 gtk_widget_hide (parent_priv->toolbar);
884 /* Font color placeholder */
885 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
886 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
889 tool_item = GTK_WIDGET (gtk_tool_item_new ());
890 priv->font_color_button = hildon_color_button_new ();
891 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
892 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
893 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
894 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
895 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
896 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
897 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
899 /* Font size and face placeholder */
900 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
901 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
903 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
904 priv->size_tool_button_label = gtk_label_new (NULL);
905 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
906 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
907 size_text,"</span>", NULL);
908 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
910 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
911 sizes_menu = gtk_menu_new ();
912 priv->size_items_group = NULL;
914 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
915 GtkWidget *size_menu_item;
917 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
918 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
919 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
920 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
921 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
922 gtk_widget_show (size_menu_item);
924 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
928 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
929 GtkWidget *item = (GtkWidget *) node->data;
930 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
934 priv->size_items_group = g_slist_reverse (priv->size_items_group);
935 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
936 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
937 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
938 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
939 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
940 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
941 priv->font_size_toolitem = tool_item;
944 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
945 priv->font_tool_button_label = gtk_label_new (NULL);
946 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
947 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
949 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
950 fonts_menu = gtk_menu_new ();
951 priv->font_items_group = NULL;
953 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
954 GtkWidget *font_menu_item;
955 GtkWidget *child_label;
957 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
958 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
959 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
960 wp_get_font_name (font_index), "</span>", NULL);
961 gtk_label_set_markup (GTK_LABEL (child_label), markup);
964 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
965 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
966 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
967 gtk_widget_show (font_menu_item);
969 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
972 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
973 GtkWidget *item = (GtkWidget *) node->data;
974 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
977 priv->font_items_group = g_slist_reverse (priv->font_items_group);
978 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
979 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
980 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
981 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
982 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
983 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
984 priv->font_face_toolitem = tool_item;
986 /* Set expand and homogeneous for remaining items */
987 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
988 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
989 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
990 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
991 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
992 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
993 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
994 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
995 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1003 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name)
1006 ModestWindowPrivate *parent_priv;
1007 ModestMsgEditWindowPrivate *priv;
1008 GtkActionGroup *action_group;
1009 GError *error = NULL;
1010 GdkPixbuf *window_icon = NULL;
1013 gboolean prefer_formatted;
1015 ModestPair *account_pair = NULL;
1017 g_return_val_if_fail (msg, NULL);
1018 g_return_val_if_fail (account_name, NULL);
1020 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
1022 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1023 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1025 parent_priv->ui_manager = gtk_ui_manager_new();
1026 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
1027 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1029 /* Add common actions */
1030 gtk_action_group_add_actions (action_group,
1031 modest_msg_edit_action_entries,
1032 G_N_ELEMENTS (modest_msg_edit_action_entries),
1034 gtk_action_group_add_toggle_actions (action_group,
1035 modest_msg_edit_toggle_action_entries,
1036 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
1038 gtk_action_group_add_radio_actions (action_group,
1039 modest_msg_edit_alignment_radio_action_entries,
1040 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
1042 G_CALLBACK (modest_ui_actions_on_change_justify),
1044 gtk_action_group_add_radio_actions (action_group,
1045 modest_msg_edit_zoom_action_entries,
1046 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
1048 G_CALLBACK (modest_ui_actions_on_change_zoom),
1050 gtk_action_group_add_radio_actions (action_group,
1051 modest_msg_edit_priority_action_entries,
1052 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
1054 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
1056 gtk_action_group_add_radio_actions (action_group,
1057 modest_msg_edit_file_format_action_entries,
1058 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
1059 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
1060 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
1062 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1063 g_object_unref (action_group);
1065 /* Load the UI definition */
1066 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
1068 if (error != NULL) {
1069 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
1070 g_clear_error (&error);
1073 /* Add accelerators */
1074 gtk_window_add_accel_group (GTK_WINDOW (obj),
1075 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1078 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
1079 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1082 init_window (MODEST_MSG_EDIT_WINDOW(obj));
1084 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1086 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1088 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1089 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1091 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
1093 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
1094 if (account_pair != NULL)
1095 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
1097 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg);
1099 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1101 /* Set window icon */
1102 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
1104 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1105 g_object_unref (window_icon);
1108 /* Dim at start clipboard actions */
1109 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
1110 gtk_action_set_sensitive (action, FALSE);
1111 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
1112 gtk_action_set_sensitive (action, FALSE);
1113 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
1114 gtk_action_set_sensitive (action, FALSE);
1116 /* Update select all */
1117 update_select_all_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1118 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu");
1119 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (edit_menu_activated), obj);
1120 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu");
1121 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (view_menu_activated), obj);
1123 /* set initial state of cc and bcc */
1124 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
1125 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1126 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
1127 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
1128 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1129 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
1131 /* Setup the file format */
1132 conf = modest_runtime_get_conf ();
1133 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
1135 g_clear_error (&error);
1136 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
1138 file_format = (prefer_formatted) ?
1139 MODEST_FILE_FORMAT_FORMATTED_TEXT :
1140 MODEST_FILE_FORMAT_PLAIN_TEXT;
1141 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
1143 update_paste_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1144 priv->update_caption_visibility = TRUE;
1146 return (ModestWindow*) obj;
1150 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1152 GString **string_buffer = (GString **) user_data;
1154 *string_buffer = g_string_append (*string_buffer, buffer);
1160 * @result: A new string which should be freed with g_free().
1163 get_formatted_data (ModestMsgEditWindow *edit_window)
1165 ModestMsgEditWindowPrivate *priv;
1166 GString *string_buffer = g_string_new ("");
1168 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1170 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1172 return g_string_free (string_buffer, FALSE);
1177 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1180 const gchar *account_name;
1181 ModestMsgEditWindowPrivate *priv;
1183 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1185 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1187 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1188 g_return_val_if_fail (account_name, NULL);
1191 /* don't free these (except from) */
1192 data = g_slice_new0 (MsgData);
1193 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1195 data->account_name = g_strdup (account_name);
1196 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1197 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1198 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1199 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1200 if (priv->draft_msg) {
1201 data->draft_msg = g_object_ref (priv->draft_msg);
1203 if (priv->outbox_msg) {
1204 data->draft_msg = g_object_ref (priv->outbox_msg);
1206 data->draft_msg = NULL;
1209 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1211 gtk_text_buffer_get_bounds (buf, &b, &e);
1212 data->plain_body = g_strdup (gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE)); /* returns a copy */
1214 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1215 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1217 data->html_body = NULL;
1219 /* deep-copy the data */
1220 GList *cursor = priv->attachments;
1221 data->attachments = NULL;
1223 if (!(TNY_IS_MIME_PART(cursor->data))) {
1224 g_warning ("strange data in attachment list");
1225 cursor = g_list_next (cursor);
1228 data->attachments = g_list_append (data->attachments,
1229 g_object_ref (cursor->data));
1230 cursor = g_list_next (cursor);
1233 data->priority_flags = priv->priority_flags;
1240 unref_gobject (GObject *obj, gpointer data)
1242 if (!G_IS_OBJECT(obj))
1244 g_object_unref (obj);
1248 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1251 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1259 g_free (data->subject);
1260 g_free (data->plain_body);
1261 g_free (data->html_body);
1262 g_free (data->account_name);
1264 if (data->draft_msg != NULL) {
1265 g_object_unref (data->draft_msg);
1266 data->draft_msg = NULL;
1269 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1270 g_list_free (data->attachments);
1272 g_slice_free (MsgData, data);
1276 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1279 ModestMsgEditWindowPrivate *priv = NULL;
1280 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1282 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1284 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1286 return MODEST_MSG_EDIT_FORMAT_HTML;
1288 return MODEST_MSG_EDIT_FORMAT_TEXT;
1292 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1293 ModestMsgEditFormat format)
1295 ModestMsgEditWindowPrivate *priv;
1297 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1298 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1301 case MODEST_MSG_EDIT_FORMAT_HTML:
1302 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1304 case MODEST_MSG_EDIT_FORMAT_TEXT:
1305 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1308 g_return_if_reached ();
1312 ModestMsgEditFormatState *
1313 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1315 ModestMsgEditFormatState *format_state = NULL;
1316 ModestMsgEditWindowPrivate *priv;
1317 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1319 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1320 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1322 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1324 format_state = g_new0 (ModestMsgEditFormatState, 1);
1325 format_state->bold = buffer_format->bold&0x1;
1326 format_state->italics = buffer_format->italic&0x1;
1327 format_state->bullet = buffer_format->bullet&0x1;
1328 format_state->color = buffer_format->color;
1329 format_state->font_size = buffer_format->font_size;
1330 format_state->font_family = wp_get_font_name (buffer_format->font);
1331 format_state->justification = buffer_format->justification;
1332 g_free (buffer_format);
1334 return format_state;
1339 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1340 const ModestMsgEditFormatState *format_state)
1342 ModestMsgEditWindowPrivate *priv;
1343 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1344 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1345 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1346 g_return_if_fail (format_state != NULL);
1348 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1349 gtk_widget_grab_focus (priv->msg_body);
1350 buffer_format->bold = (format_state->bold != FALSE);
1351 buffer_format->italic = (format_state->italics != FALSE);
1352 buffer_format->color = format_state->color;
1353 buffer_format->font_size = format_state->font_size;
1354 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1355 buffer_format->justification = format_state->justification;
1356 buffer_format->bullet = format_state->bullet;
1358 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1360 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1361 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1362 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1363 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1364 buffer_format->cs.font = (buffer_format->font != current_format->font);
1365 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1366 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1368 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1369 if (buffer_format->cs.bold) {
1370 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1372 if (buffer_format->cs.italic) {
1373 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1375 if (buffer_format->cs.color) {
1376 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1378 if (buffer_format->cs.font_size) {
1379 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1381 if (buffer_format->cs.justification) {
1382 switch (buffer_format->justification) {
1383 case GTK_JUSTIFY_LEFT:
1384 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1386 case GTK_JUSTIFY_CENTER:
1387 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1389 case GTK_JUSTIFY_RIGHT:
1390 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1397 if (buffer_format->cs.font) {
1398 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1400 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1401 if (buffer_format->cs.bullet) {
1402 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((buffer_format->bullet)?1:0));
1404 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1406 g_free (current_format);
1411 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1413 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1415 ModestWindowPrivate *parent_priv;
1416 ModestMsgEditWindowPrivate *priv;
1417 GtkWidget *new_size_menuitem;
1418 GtkWidget *new_font_menuitem;
1420 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1421 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1423 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1424 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1425 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1426 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1428 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1429 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1430 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1433 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1435 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1436 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1438 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1439 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1441 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1442 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1444 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1445 G_CALLBACK (modest_msg_edit_window_color_button_change),
1447 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1448 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1449 G_CALLBACK (modest_msg_edit_window_color_button_change),
1452 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1453 buffer_format->font_size))->data);
1454 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1458 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1459 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1460 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1462 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1463 G_CALLBACK (modest_msg_edit_window_size_change),
1465 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1466 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1467 G_CALLBACK (modest_msg_edit_window_size_change),
1471 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1472 buffer_format->font))->data);
1473 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1477 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1478 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1479 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1481 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1482 G_CALLBACK (modest_msg_edit_window_font_change),
1484 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1485 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1486 G_CALLBACK (modest_msg_edit_window_font_change),
1490 g_free (buffer_format);
1496 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1499 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1500 ModestMsgEditWindowPrivate *priv;
1501 GtkWidget *dialog = NULL;
1503 const GdkColor *new_color = NULL;
1505 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1506 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1508 #ifdef MODEST_HILDON_VERSION_0
1509 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1510 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1512 dialog = hildon_color_chooser_new ();
1513 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1514 #endif /*MODEST_HILDON_VERSION_0*/
1515 g_free (buffer_format);
1517 response = gtk_dialog_run (GTK_DIALOG (dialog));
1519 case GTK_RESPONSE_OK: {
1520 #ifdef MODEST_HILDON_VERSION_0
1521 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1524 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1526 #endif /*MODEST_HILDON_VERSION_0*/
1533 gtk_widget_destroy (dialog);
1535 if (new_color != NULL)
1536 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1541 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1544 ModestMsgEditWindowPrivate *priv;
1545 GtkWidget *dialog = NULL;
1547 GdkColor *old_color = NULL;
1548 const GdkColor *new_color = NULL;
1550 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1551 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1553 #ifdef MODEST_HILDON_VERSION_0
1554 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1555 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1557 dialog = hildon_color_chooser_new ();
1558 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1559 #endif /*MODEST_HILDON_VERSION_9*/
1561 response = gtk_dialog_run (GTK_DIALOG (dialog));
1563 case GTK_RESPONSE_OK: {
1564 #ifdef MODEST_HILDON_VERSION_0
1565 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1568 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1570 #endif /*MODEST_HILDON_VERSION_0*/
1576 gtk_widget_destroy (dialog);
1578 if (new_color != NULL)
1579 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1583 static TnyStream* create_stream_for_uri (const gchar* uri)
1588 TnyStream *result = NULL;
1590 GnomeVFSHandle *handle = NULL;
1591 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1592 if (test == GNOME_VFS_OK) {
1593 /* Create the tinymail stream: */
1594 /* Presumably tinymai will call gnome_vfs_close (handle) later. */
1595 result = TNY_STREAM (tny_vfs_stream_new (handle));
1602 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1605 ModestMsgEditWindowPrivate *priv;
1606 GtkWidget *dialog = NULL;
1608 GSList *uris = NULL;
1609 GSList *uri_node = NULL;
1611 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1613 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1614 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1615 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1617 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1619 response = gtk_dialog_run (GTK_DIALOG (dialog));
1621 case GTK_RESPONSE_OK:
1622 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1627 gtk_widget_destroy (dialog);
1629 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1631 GnomeVFSHandle *handle = NULL;
1632 GnomeVFSResult result;
1633 GtkTextIter position;
1634 GtkTextMark *insert_mark;
1636 uri = (const gchar *) uri_node->data;
1637 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1638 if (result == GNOME_VFS_OK) {
1640 GnomeVFSFileInfo info;
1641 gchar *filename, *basename, *escaped_filename;
1642 TnyMimePart *mime_part;
1644 const gchar *mime_type = NULL;
1645 GnomeVFSURI *vfs_uri;
1647 vfs_uri = gnome_vfs_uri_new (uri);
1649 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1650 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1651 g_free (escaped_filename);
1652 gnome_vfs_uri_unref (vfs_uri);
1654 if (gnome_vfs_get_file_info (uri, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
1655 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1657 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1659 mime_part = tny_platform_factory_new_mime_part
1660 (modest_runtime_get_platform_factory ());
1662 TnyStream *stream = create_stream_for_uri (uri);
1663 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1665 content_id = g_strdup_printf ("%d", priv->last_cid);
1666 tny_mime_part_set_content_id (mime_part, content_id);
1667 g_free (content_id);
1670 basename = g_path_get_basename (filename);
1671 tny_mime_part_set_filename (mime_part, basename);
1674 pixbuf = pixbuf_from_stream (stream, mime_type);
1676 if (pixbuf != NULL) {
1677 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1678 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1679 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1682 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1683 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1685 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1686 gtk_widget_show_all (priv->attachments_caption);
1687 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1697 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
1700 ModestMsgEditWindowPrivate *priv;
1701 GtkWidget *dialog = NULL;
1703 GSList *uris = NULL;
1706 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1708 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1709 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
1710 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1712 response = gtk_dialog_run (GTK_DIALOG (dialog));
1714 case GTK_RESPONSE_OK:
1715 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1720 gtk_widget_destroy (dialog);
1722 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1723 const gchar *uri = (const gchar *) uri_node->data;
1724 modest_msg_edit_window_attach_file_one (window, uri);
1726 g_slist_foreach (uris, (GFunc) g_free, NULL);
1727 g_slist_free (uris);
1731 modest_msg_edit_window_attach_file_one (
1732 ModestMsgEditWindow *window,
1735 g_return_if_fail (window);
1736 g_return_if_fail (uri);
1738 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1741 GnomeVFSHandle *handle = NULL;
1742 GnomeVFSResult result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1743 if (result == GNOME_VFS_OK) {
1744 TnyMimePart *mime_part;
1746 const gchar *mime_type = NULL;
1748 gchar *escaped_filename;
1751 GnomeVFSFileInfo info;
1752 GnomeVFSURI *vfs_uri;
1754 vfs_uri = gnome_vfs_uri_new (uri);
1757 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1758 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1759 g_free (escaped_filename);
1760 gnome_vfs_uri_unref (vfs_uri);
1762 if (gnome_vfs_get_file_info (uri,
1764 GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
1765 GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1767 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1768 mime_part = tny_platform_factory_new_mime_part
1769 (modest_runtime_get_platform_factory ());
1770 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1772 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1774 content_id = g_strdup_printf ("%d", priv->last_cid);
1775 tny_mime_part_set_content_id (mime_part, content_id);
1776 g_free (content_id);
1779 basename = g_path_get_basename (filename);
1780 tny_mime_part_set_filename (mime_part, basename);
1783 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1784 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1786 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1787 gtk_widget_show_all (priv->attachments_caption);
1788 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1794 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1797 ModestMsgEditWindowPrivate *priv;
1798 gboolean clean_list = FALSE;
1800 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1801 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1803 if (att_list == NULL) {
1804 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1808 if (att_list == NULL) {
1809 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1811 GtkWidget *confirmation_dialog = NULL;
1812 gboolean dialog_response;
1814 gchar *message = NULL;
1815 const gchar *filename = NULL;
1817 if (att_list->next == NULL) {
1818 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1822 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1823 att_list->next == NULL), filename);
1824 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1826 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1827 gtk_widget_destroy (confirmation_dialog);
1828 if (!dialog_response) {
1830 g_list_free (att_list);
1833 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1835 for (node = att_list; node != NULL; node = g_list_next (node)) {
1836 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1837 const gchar *att_id;
1838 priv->attachments = g_list_remove (priv->attachments, mime_part);
1840 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1842 if (priv->attachments == NULL)
1843 gtk_widget_hide (priv->attachments_caption);
1844 att_id = tny_mime_part_get_content_id (mime_part);
1846 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1848 g_object_unref (mime_part);
1849 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1854 g_list_free (att_list);
1858 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1861 ModestMsgEditWindowPrivate *priv;
1862 GdkColor *new_color;
1863 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1865 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1866 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1869 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1871 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1873 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1875 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1880 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1883 ModestMsgEditWindowPrivate *priv;
1884 gint new_size_index;
1885 ModestMsgEditWindow *window;
1888 window = MODEST_MSG_EDIT_WINDOW (userdata);
1889 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1890 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1892 if (gtk_check_menu_item_get_active (menu_item)) {
1894 WPTextBufferFormat format;
1896 memset (&format, 0, sizeof (format));
1897 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1899 label = gtk_bin_get_child (GTK_BIN (menu_item));
1901 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1902 format.cs.font_size = TRUE;
1903 format.cs.text_position = TRUE;
1904 format.cs.font = TRUE;
1905 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1906 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1908 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1909 (gpointer) wp_get_font_size_index (new_size_index, 12)))
1910 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1912 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1913 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1914 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1920 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1923 ModestMsgEditWindowPrivate *priv;
1924 gint new_font_index;
1925 ModestMsgEditWindow *window;
1928 window = MODEST_MSG_EDIT_WINDOW (userdata);
1929 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1930 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1932 if (gtk_check_menu_item_get_active (menu_item)) {
1935 label = gtk_bin_get_child (GTK_BIN (menu_item));
1937 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1939 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1940 (gpointer) new_font_index))
1941 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1943 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1944 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1945 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1951 modest_msg_edit_window_set_zoom (ModestWindow *window,
1954 ModestMsgEditWindowPrivate *priv;
1955 ModestWindowPrivate *parent_priv;
1956 GtkRadioAction *zoom_radio_action;
1958 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1960 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1961 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1962 priv->zoom_level = zoom;
1963 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom*DEFAULT_FONT_SCALE);
1965 /* Zoom level menu options should be updated with the current zoom level */
1966 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1967 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1968 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1969 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1970 /* FIXME: Not availible before Gtk 2.10 */
1972 gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
1977 modest_msg_edit_window_get_zoom (ModestWindow *window)
1979 ModestMsgEditWindowPrivate *priv;
1981 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1983 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1984 return priv->zoom_level;
1988 zoom_allowed (ModestMsgEditWindow *window)
1992 focus = gtk_window_get_focus (GTK_WINDOW (window));
1993 return (focus != NULL && WP_IS_TEXT_VIEW (focus));
1997 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1999 ModestWindowPrivate *parent_priv;
2000 GtkRadioAction *zoom_radio_action;
2001 GSList *group, *node;
2003 /* First we check if the text view is focused. If not, zooming is not allowed */
2004 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2005 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2009 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2010 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2011 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2013 group = gtk_radio_action_get_group (zoom_radio_action);
2015 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
2016 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
2020 for (node = group; node != NULL; node = g_slist_next (node)) {
2021 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
2022 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
2030 modest_msg_edit_window_zoom_minus (ModestWindow *window)
2032 ModestWindowPrivate *parent_priv;
2033 GtkRadioAction *zoom_radio_action;
2034 GSList *group, *node;
2036 /* First we check if the text view is focused. If not, zooming is not allowed */
2037 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2038 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2042 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2043 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2044 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2046 group = gtk_radio_action_get_group (zoom_radio_action);
2048 for (node = group; node != NULL; node = g_slist_next (node)) {
2049 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
2050 if (node->next != NULL) {
2051 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
2054 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
2062 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2064 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2065 ModestWindowPrivate *parent_priv;
2066 ModestWindowMgr *mgr;
2067 gboolean is_fullscreen;
2068 GtkAction *fs_toggle_action;
2071 mgr = modest_runtime_get_window_mgr ();
2072 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2074 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2076 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2077 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2078 if (is_fullscreen != active)
2079 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2087 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
2089 ModestWindowPrivate *parent_priv;
2090 GtkAction *fs_toggle_action;
2093 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2095 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2096 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
2097 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
2101 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2104 ModestMsgEditWindowPrivate *priv = NULL;
2105 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2107 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2108 if (!priv->update_caption_visibility)
2111 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2113 gtk_widget_show (priv->cc_caption);
2115 gtk_widget_hide (priv->cc_caption);
2117 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2121 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2124 ModestMsgEditWindowPrivate *priv = NULL;
2125 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2127 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2128 if (!priv->update_caption_visibility)
2131 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2133 gtk_widget_show (priv->bcc_caption);
2135 gtk_widget_hide (priv->bcc_caption);
2137 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2141 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2142 ModestRecptEditor *editor)
2144 ModestMsgEditWindowPrivate *priv;
2146 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2147 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2148 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2150 if (editor == NULL) {
2151 GtkWidget *view_focus;
2152 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2154 /* This code should be kept in sync with ModestRecptEditor. The
2155 textview inside the recpt editor is the one that really gets the
2156 focus. As it's inside a scrolled window, and this one inside the
2157 hbox recpt editor inherits from, we'll need to go up in the
2158 hierarchy to know if the text view is part of the recpt editor
2159 or if it's a different text entry */
2161 if (gtk_widget_get_parent (view_focus)) {
2162 GtkWidget *first_parent;
2164 first_parent = gtk_widget_get_parent (view_focus);
2165 if (gtk_widget_get_parent (first_parent) &&
2166 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2167 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2172 editor = MODEST_RECPT_EDITOR (priv->to_field);
2176 modest_address_book_select_addresses (editor);
2181 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2183 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2185 modest_msg_edit_window_open_addressbook (window, NULL);
2189 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2190 gboolean show_toolbar)
2192 ModestWindowPrivate *parent_priv;
2194 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2195 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2197 /* FIXME: we can not just use the code of
2198 modest_msg_edit_window_setup_toolbar because it has a
2199 mixture of both initialization and creation code. */
2202 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2204 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2208 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2209 TnyHeaderFlags priority_flags)
2211 ModestMsgEditWindowPrivate *priv;
2212 ModestWindowPrivate *parent_priv;
2214 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2216 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2217 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2218 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2220 if (priv->priority_flags != priority_flags) {
2221 GtkAction *priority_action = NULL;
2223 priv->priority_flags = priority_flags;
2225 switch (priority_flags) {
2226 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2227 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2228 gtk_widget_show (priv->priority_icon);
2229 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2230 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2232 case TNY_HEADER_FLAG_LOW_PRIORITY:
2233 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", 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/MessagePriorityLowMenu");
2239 gtk_widget_hide (priv->priority_icon);
2240 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2241 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2244 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2245 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2250 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2253 ModestMsgEditWindowPrivate *priv;
2254 ModestWindowPrivate *parent_priv;
2255 gint current_format;
2257 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2259 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2260 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2262 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2263 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2265 if (current_format != file_format) {
2266 switch (file_format) {
2267 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2268 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2270 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2274 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2275 response = gtk_dialog_run (GTK_DIALOG (dialog));
2276 gtk_widget_destroy (dialog);
2277 if (response == GTK_RESPONSE_OK) {
2278 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2280 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2281 modest_maemo_toggle_action_set_active_block_notify (action, TRUE);
2286 update_dimmed (window);
2291 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2294 ModestMsgEditWindowPrivate *priv;
2295 WPTextBufferFormat oldfmt, fmt;
2296 gint old_position = 0;
2300 GdkColor *color = NULL;
2301 gboolean bold, bold_set, italic, italic_set;
2302 gboolean underline, underline_set;
2303 gboolean strikethrough, strikethrough_set;
2304 gboolean position_set;
2305 gboolean font_size_set, font_set, color_set;
2308 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2309 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2311 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2313 /* First we get the currently selected font information */
2314 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2315 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2317 switch (oldfmt.text_position) {
2318 case TEXT_POSITION_NORMAL:
2321 case TEXT_POSITION_SUPERSCRIPT:
2329 g_object_set (G_OBJECT (dialog),
2330 "bold", oldfmt.bold != FALSE,
2331 "bold-set", !oldfmt.cs.bold,
2332 "underline", oldfmt.underline != FALSE,
2333 "underline-set", !oldfmt.cs.underline,
2334 "italic", oldfmt.italic != FALSE,
2335 "italic-set", !oldfmt.cs.italic,
2336 "strikethrough", oldfmt.strikethrough != FALSE,
2337 "strikethrough-set", !oldfmt.cs.strikethrough,
2338 "color", &oldfmt.color,
2339 "color-set", !oldfmt.cs.color,
2340 "size", wp_font_size[oldfmt.font_size],
2341 "size-set", !oldfmt.cs.font_size,
2342 "position", old_position,
2343 "position-set", !oldfmt.cs.text_position,
2344 "family", wp_get_font_name (oldfmt.font),
2345 "family-set", !oldfmt.cs.font,
2348 gtk_widget_show_all (dialog);
2349 response = gtk_dialog_run (GTK_DIALOG (dialog));
2350 if (response == GTK_RESPONSE_OK) {
2352 g_object_get( dialog,
2354 "bold-set", &bold_set,
2355 "underline", &underline,
2356 "underline-set", &underline_set,
2358 "italic-set", &italic_set,
2359 "strikethrough", &strikethrough,
2360 "strikethrough-set", &strikethrough_set,
2362 "color-set", &color_set,
2364 "size-set", &font_size_set,
2365 "family", &font_name,
2366 "family-set", &font_set,
2367 "position", &position,
2368 "position-set", &position_set,
2373 if (response == GTK_RESPONSE_OK) {
2374 memset(&fmt, 0, sizeof(fmt));
2380 fmt.italic = italic;
2381 fmt.cs.italic = TRUE;
2383 if (underline_set) {
2384 fmt.underline = underline;
2385 fmt.cs.underline = TRUE;
2387 if (strikethrough_set) {
2388 fmt.strikethrough = strikethrough;
2389 fmt.cs.strikethrough = TRUE;
2394 ? TEXT_POSITION_NORMAL
2395 : ( ( position == 1 )
2396 ? TEXT_POSITION_SUPERSCRIPT
2397 : TEXT_POSITION_SUBSCRIPT );
2398 fmt.cs.text_position = TRUE;
2402 fmt.cs.color = TRUE;
2405 fmt.font = wp_get_font_index(font_name,
2410 if (font_size_set) {
2411 fmt.font_size = wp_get_font_size_index(
2412 font_size, DEFAULT_FONT_SIZE);
2413 fmt.cs.font_size = TRUE;
2415 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2417 gtk_widget_destroy (dialog);
2419 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2423 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2425 ModestMsgEditWindowPrivate *priv;
2427 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2428 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2430 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2432 update_dimmed (window);
2437 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2439 ModestMsgEditWindowPrivate *priv;
2441 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2442 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2444 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2446 update_dimmed (window);
2451 update_dimmed (ModestMsgEditWindow *window)
2453 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2454 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2458 gboolean editor_focused;
2460 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2461 editor_focused = gtk_widget_is_focus (priv->msg_body);
2463 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2464 gtk_action_set_sensitive (action, rich_text && editor_focused);
2465 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2466 gtk_action_set_sensitive (action, rich_text && editor_focused);
2467 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2468 gtk_action_set_sensitive (action, rich_text && editor_focused);
2469 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2470 gtk_action_set_sensitive (action, rich_text && editor_focused);
2471 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2472 gtk_action_set_sensitive (action, rich_text && editor_focused);
2473 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2474 gtk_action_set_sensitive (action, rich_text && editor_focused);
2475 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2476 gtk_action_set_sensitive (action, rich_text && editor_focused);
2477 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2478 gtk_action_set_sensitive (action, rich_text && editor_focused);
2479 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2480 gtk_action_set_sensitive (action, rich_text && editor_focused);
2481 widget = priv->font_color_button;
2482 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2483 widget = priv->font_size_toolitem;
2484 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2485 widget = priv->font_face_toolitem;
2486 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2490 setup_insensitive_handlers (ModestMsgEditWindow *window)
2492 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2493 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2496 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2497 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2498 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2499 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2500 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2501 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2502 widget = priv->font_color_button;
2503 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2504 widget = priv->font_size_toolitem;
2505 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2506 widget = priv->font_face_toolitem;
2507 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2512 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2514 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2517 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2518 gtk_action_set_sensitive (action, can_undo);
2522 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2524 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2527 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/RedoMenu");
2528 gtk_action_set_sensitive (action, can_redo);
2532 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2535 GtkTextIter match_start, match_end;
2537 if (image_id == NULL)
2540 gtk_text_buffer_get_start_iter (buffer, &iter);
2542 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2543 GSList *tags = gtk_text_iter_get_tags (&match_start);
2545 for (node = tags; node != NULL; node = g_slist_next (node)) {
2546 GtkTextTag *tag = (GtkTextTag *) node->data;
2547 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2548 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2549 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2551 offset = gtk_text_iter_get_offset (&match_start);
2552 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2553 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2557 gtk_text_iter_forward_char (&iter);
2562 msg_body_focus (GtkWidget *focus,
2563 GdkEventFocus *event,
2567 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2572 recpt_field_changed (GtkTextBuffer *buffer,
2573 ModestMsgEditWindow *editor)
2575 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2576 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2577 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2578 gboolean dim = FALSE;
2581 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2582 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2583 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2585 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2586 gtk_text_buffer_get_char_count (cc_buffer) +
2587 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2589 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2590 gtk_action_set_sensitive (action, !dim);
2591 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2592 gtk_action_set_sensitive (action, !dim);
2596 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2598 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2602 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2604 gboolean rich_text, editor_focused;
2606 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2607 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2608 editor_focused = gtk_widget_is_focus (priv->msg_body);
2611 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2612 else if (!editor_focused)
2613 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2617 reset_modified (ModestMsgEditWindow *editor)
2619 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2620 GtkTextBuffer *buffer;
2622 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2623 gtk_text_buffer_set_modified (buffer, FALSE);
2624 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2625 gtk_text_buffer_set_modified (buffer, FALSE);
2626 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2627 gtk_text_buffer_set_modified (buffer, FALSE);
2628 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2632 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2634 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2635 GtkTextBuffer *buffer;
2637 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2638 if (gtk_text_buffer_get_modified (buffer))
2640 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2641 if (gtk_text_buffer_get_modified (buffer))
2643 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2644 if (gtk_text_buffer_get_modified (buffer))
2646 if (gtk_text_buffer_get_modified (priv->text_buffer))
2653 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
2655 ModestMsgEditWindowPrivate *priv = NULL;
2657 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2658 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2660 /* check if there's no recipient added */
2661 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2662 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2663 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2664 /* no recipient contents, then select contacts */
2665 modest_msg_edit_window_open_addressbook (window, NULL);
2669 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook))
2671 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook))
2673 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook))
2676 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2683 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2684 ModestMsgEditWindow *window)
2686 modest_msg_edit_window_offer_attach_file (window);
2690 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2692 ModestMsgEditWindow *window)
2694 ModestWindowPrivate *parent_priv;
2695 ModestMsgEditWindowPrivate *priv;
2697 gboolean has_selection;
2699 GList *selected_attachments = NULL;
2700 gint n_att_selected = 0;
2702 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2703 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2705 if (!GTK_WIDGET_VISIBLE (window))
2707 has_selection = gtk_clipboard_wait_for_targets (clipboard, NULL, NULL);
2708 focused = gtk_window_get_focus (GTK_WINDOW (window));
2710 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2711 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2712 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2713 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2715 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2716 n_att_selected = g_list_length (selected_attachments);
2717 g_list_free (selected_attachments);
2719 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2720 gtk_action_set_sensitive (action, n_att_selected == 1);
2722 update_paste_dimming (window);
2726 update_window_title (ModestMsgEditWindow *window)
2728 ModestMsgEditWindowPrivate *priv = NULL;
2729 const gchar *subject;
2731 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2732 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2733 if (subject == NULL || subject[0] == '\0')
2734 subject = _("mail_va_new_email");
2736 gtk_window_set_title (GTK_WINDOW (window), subject);
2741 subject_field_changed (GtkEditable *editable,
2742 ModestMsgEditWindow *window)
2744 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2745 update_window_title (window);
2746 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2750 message_is_empty (ModestMsgEditWindow *window)
2752 ModestMsgEditWindowPrivate *priv = NULL;
2754 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2755 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2757 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
2758 * so we can ignore markup.
2760 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
2763 count = gtk_text_buffer_get_char_count (buf);
2769 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2772 ModestMsgEditWindowPrivate *priv = NULL;
2774 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2775 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2777 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2780 gtk_widget_show_all (priv->find_toolbar);
2781 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2783 gtk_widget_hide_all (priv->find_toolbar);
2784 gtk_widget_grab_focus (priv->msg_body);
2790 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2792 GtkTextIter *match_start,
2793 GtkTextIter *match_end)
2795 GtkTextIter end_iter;
2796 gchar *str_casefold;
2799 gchar *range_casefold;
2802 gboolean result = FALSE;
2809 gtk_text_iter_forward_to_end (&end_iter);
2811 str_casefold = g_utf8_casefold (str, -1);
2812 str_chars_n = strlen (str);
2814 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2815 range_casefold = g_utf8_casefold (range_text, -1);
2816 range_chars_n = strlen (range_casefold);
2818 if (range_chars_n < str_chars_n) {
2819 g_free (str_casefold);
2820 g_free (range_text);
2821 g_free (range_casefold);
2825 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2826 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2827 if (!g_utf8_collate (range_subtext, str_casefold)) {
2828 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2830 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2831 match_start, match_end, NULL);
2832 g_free (found_text);
2834 g_free (range_subtext);
2838 g_free (str_casefold);
2839 g_free (range_text);
2840 g_free (range_casefold);
2847 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2848 ModestMsgEditWindow *window)
2850 gchar *current_search = NULL;
2851 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2853 GtkTextIter selection_start, selection_end;
2854 GtkTextIter match_start, match_end;
2855 gboolean continue_search = FALSE;
2857 if (message_is_empty (window)) {
2858 g_free (priv->last_search);
2859 priv->last_search = NULL;
2860 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
2864 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2865 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2866 g_free (current_search);
2867 g_free (priv->last_search);
2868 priv->last_search = NULL;
2869 /* Information banner about empty search */
2870 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2874 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2875 continue_search = TRUE;
2877 g_free (priv->last_search);
2878 priv->last_search = g_strdup (current_search);
2881 if (continue_search) {
2882 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2883 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2884 &match_start, &match_end);
2886 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2888 GtkTextIter buffer_start;
2889 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2890 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2891 &match_start, &match_end);
2893 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2896 /* Mark as selected the string found in search */
2898 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2899 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2901 g_free (priv->last_search);
2902 priv->last_search = NULL;
2904 g_free (current_search);
2908 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2909 ModestMsgEditWindow *window)
2911 GtkToggleAction *toggle;
2912 ModestWindowPrivate *parent_priv;
2913 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2915 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2916 gtk_toggle_action_set_active (toggle, FALSE);
2921 update_paste_dimming (ModestMsgEditWindow *window)
2923 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2924 GtkAction *action = NULL;
2925 GtkClipboard *clipboard = NULL;
2926 ModestEmailClipboard *e_clipboard;
2930 focused = gtk_window_get_focus (GTK_WINDOW (window));
2932 e_clipboard = modest_runtime_get_email_clipboard ();
2933 if (!modest_email_clipboard_cleared (e_clipboard)) {
2936 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2937 active = gtk_clipboard_wait_is_text_available (clipboard);
2941 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2945 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2946 gtk_action_set_sensitive (action, active);
2951 update_select_all_dimming (ModestMsgEditWindow *window)
2954 gboolean dimmed = FALSE;
2956 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2958 focused = gtk_window_get_focus (GTK_WINDOW (window));
2959 if (GTK_IS_ENTRY (focused)) {
2960 const gchar *current_text;
2961 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
2962 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
2963 } else if (GTK_IS_TEXT_VIEW (focused)) {
2964 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
2965 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
2966 } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
2969 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
2970 gtk_action_set_sensitive (action, !dimmed);
2974 update_zoom_dimming (ModestMsgEditWindow *window)
2977 gboolean dimmed = FALSE;
2979 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2981 focused = gtk_window_get_focus (GTK_WINDOW (window));
2982 dimmed = ! WP_IS_TEXT_VIEW (focused);
2983 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2984 gtk_action_set_sensitive (action, !dimmed);
2988 edit_menu_activated (GtkAction *action,
2991 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2993 update_select_all_dimming (window);
2994 update_paste_dimming (window);
2997 view_menu_activated (GtkAction *action,
3000 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3002 update_zoom_dimming (window);
3006 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3008 ModestMsgEditWindowPrivate *priv;
3010 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3015 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3018 ModestMsgEditWindowPrivate *priv;
3020 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3026 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3029 ModestMsgEditWindowPrivate *priv;
3030 TnyHeader *header = NULL;
3032 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3033 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3035 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3036 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3038 if (priv->draft_msg != NULL) {
3039 header = tny_msg_get_header (priv->draft_msg);
3040 if (TNY_IS_HEADER (header)) {
3041 modest_window_mgr_unregister_header (mgr, header);
3043 g_object_unref (priv->draft_msg);
3046 if (draft != NULL) {
3047 g_object_ref (draft);
3048 header = tny_msg_get_header (draft);
3049 if (TNY_IS_HEADER (header))
3050 modest_window_mgr_register_header (mgr, header);
3053 priv->draft_msg = draft;
3057 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3058 GtkTextIter *start, GtkTextIter *end,
3061 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3062 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3065 if (tag == NULL+13) return;
3066 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3067 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3068 replace_with_attachments (window, priv->attachments);
3073 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3076 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3078 g_return_if_fail (TNY_IS_MIME_PART (part));
3079 priv->attachments = g_list_prepend (priv->attachments, part);
3080 g_object_ref (part);
3081 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part);
3082 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3083 gtk_widget_show_all (priv->attachments_caption);
3084 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);