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_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata);
101 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
102 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
103 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
104 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
105 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
107 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
109 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
111 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
112 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
113 GdkEventWindowState *event,
115 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
116 ModestRecptEditor *editor);
117 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
118 ModestMsgEditWindow *window);
120 /* ModestWindow methods implementation */
121 static void modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom);
122 static gdouble modest_msg_edit_window_get_zoom (ModestWindow *window);
123 static gboolean modest_msg_edit_window_zoom_minus (ModestWindow *window);
124 static gboolean modest_msg_edit_window_zoom_plus (ModestWindow *window);
125 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
126 gboolean show_toolbar);
127 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
129 ModestMsgEditWindow *window);
130 static void update_window_title (ModestMsgEditWindow *window);
131 static void update_dimmed (ModestMsgEditWindow *window);
132 static void update_paste_dimming (ModestMsgEditWindow *window);
133 static void update_select_all_dimming (ModestMsgEditWindow *window);
134 static void update_zoom_dimming (ModestMsgEditWindow *window);
137 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
138 ModestMsgEditWindow *window);
139 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
140 ModestMsgEditWindow *window);
141 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
143 GtkTextIter *match_start,
144 GtkTextIter *match_end);
148 /* static gboolean */
149 /* on_key_pressed (GtkWidget *self, */
150 /* GdkEventKey *event, */
151 /* gpointer user_data); */
153 static void edit_menu_activated (GtkAction *action,
155 static void view_menu_activated (GtkAction *action,
158 /* list my signals */
165 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
166 struct _ModestMsgEditWindowPrivate {
168 GtkWidget *header_box;
170 ModestPairList *from_field_protos;
171 GtkWidget *from_field;
175 GtkWidget *bcc_field;
176 GtkWidget *subject_field;
177 GtkWidget *attachments_view;
178 GtkWidget *priority_icon;
179 GtkWidget *add_attachment_button;
181 GtkWidget *cc_caption;
182 GtkWidget *bcc_caption;
183 GtkWidget *attachments_caption;
185 GtkTextBuffer *text_buffer;
187 GtkWidget *font_size_toolitem;
188 GtkWidget *font_face_toolitem;
189 GtkWidget *font_color_button;
190 GSList *font_items_group;
191 GtkWidget *font_tool_button_label;
192 GSList *size_items_group;
193 GtkWidget *size_tool_button_label;
195 GtkWidget *find_toolbar;
199 GtkWidget *scroll_area;
204 TnyHeaderFlags priority_flags;
208 gulong clipboard_change_handler_id;
214 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
215 MODEST_TYPE_MSG_EDIT_WINDOW, \
216 ModestMsgEditWindowPrivate))
218 static GtkWindowClass *parent_class = NULL;
220 /* uncomment the following if you have defined any signals */
221 /* static guint signals[LAST_SIGNAL] = {0}; */
224 modest_msg_edit_window_get_type (void)
226 static GType my_type = 0;
228 static const GTypeInfo my_info = {
229 sizeof(ModestMsgEditWindowClass),
230 NULL, /* base init */
231 NULL, /* base finalize */
232 (GClassInitFunc) modest_msg_edit_window_class_init,
233 NULL, /* class finalize */
234 NULL, /* class data */
235 sizeof(ModestMsgEditWindow),
237 (GInstanceInitFunc) modest_msg_edit_window_init,
240 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
241 "ModestMsgEditWindow",
244 wp_text_buffer_library_init ();
250 save_state (ModestWindow *self)
252 modest_widget_memory_save (modest_runtime_get_conf(),
253 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
258 restore_settings (ModestMsgEditWindow *self)
260 modest_widget_memory_restore (modest_runtime_get_conf(),
261 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
266 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
268 GObjectClass *gobject_class;
269 ModestWindowClass *modest_window_class;
270 gobject_class = (GObjectClass*) klass;
271 modest_window_class = (ModestWindowClass*) klass;
273 parent_class = g_type_class_peek_parent (klass);
274 gobject_class->finalize = modest_msg_edit_window_finalize;
276 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
277 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
278 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
279 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
280 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
281 modest_window_class->save_state_func = save_state;
283 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
289 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
291 ModestMsgEditWindowPrivate *priv;
292 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
294 priv->msg_body = NULL;
295 priv->from_field = NULL;
296 priv->to_field = NULL;
297 priv->cc_field = NULL;
298 priv->bcc_field = NULL;
299 priv->subject_field = NULL;
300 priv->attachments = NULL;
302 priv->zoom_level = 1.0;
304 priv->cc_caption = NULL;
305 priv->bcc_caption = NULL;
307 priv->priority_flags = 0;
309 priv->find_toolbar = NULL;
310 priv->last_search = NULL;
312 priv->draft_msg = NULL;
313 priv->clipboard_change_handler_id = 0;
318 /* FIXME: this is a dup from the one in gtk/ */
321 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
323 static ModestPairList*
324 get_transports (void)
326 GSList *transports = NULL;
328 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
329 GSList *accounts = modest_account_mgr_account_names (account_mgr,
330 TRUE /* only enabled accounts. */);
332 GSList *cursor = accounts;
334 gchar *account_name = cursor->data;
335 gchar *from_string = NULL;
337 from_string = modest_account_mgr_get_from_string (account_mgr,
341 if (from_string && account_name) {
342 gchar *name = account_name;
343 ModestPair *pair = modest_pair_new ((gpointer) name,
344 (gpointer) from_string , TRUE);
345 transports = g_slist_prepend (transports, pair);
348 cursor = cursor->next;
350 g_slist_free (accounts); /* only free the accounts, not the elements,
351 * because they are used in the pairlist */
357 init_window (ModestMsgEditWindow *obj)
359 GtkWidget *from_caption, *to_caption, *subject_caption;
360 GtkWidget *main_vbox;
361 ModestMsgEditWindowPrivate *priv;
363 GtkSizeGroup *size_group;
365 GtkWidget *subject_box;
366 GtkWidget *attachment_icon;
367 GtkWidget *window_box;
369 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
371 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
373 /* Note: This ModestPairList* must exist for as long as the combo
374 * that uses it, because the ModestComboBox uses the ID opaquely,
375 * so it can't know how to manage its memory. */
376 priv->from_field_protos = get_transports ();
378 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
380 priv->to_field = modest_recpt_editor_new ();
381 priv->cc_field = modest_recpt_editor_new ();
382 priv->bcc_field = modest_recpt_editor_new ();
383 subject_box = gtk_hbox_new (FALSE, 0);
384 priv->priority_icon = gtk_image_new ();
385 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
386 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
387 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
388 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
389 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
390 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
391 priv->add_attachment_button = gtk_button_new ();
392 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
393 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
394 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
395 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
396 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
397 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
398 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
399 priv->attachments_view = modest_attachments_view_new (NULL);
401 priv->header_box = gtk_vbox_new (FALSE, 0);
403 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
404 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
405 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
406 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
407 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
408 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
409 g_object_unref (size_group);
411 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
412 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
413 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
414 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
415 gtk_size_group_add_widget (size_group, priv->subject_field);
416 gtk_size_group_add_widget (size_group, priv->attachments_view);
417 g_object_unref (size_group);
419 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
420 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
421 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
422 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
423 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
424 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
425 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
428 priv->msg_body = wp_text_view_new ();
429 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
430 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
431 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
432 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
433 #if (GTK_MINOR_VERSION >= 10)
434 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
435 gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
437 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
439 priv->find_toolbar = hildon_find_toolbar_new (NULL);
440 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
442 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
444 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
445 G_CALLBACK (text_buffer_refresh_attributes), obj);
446 g_signal_connect (G_OBJECT (priv->text_buffer), "delete-range",
447 G_CALLBACK (text_buffer_delete_range), obj);
448 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
449 G_CALLBACK (text_buffer_can_undo), obj);
450 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
451 G_CALLBACK (text_buffer_can_redo), obj);
452 g_signal_connect (G_OBJECT (obj), "window-state-event",
453 G_CALLBACK (modest_msg_edit_window_window_state_event),
455 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
456 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
457 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
458 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
459 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
460 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
462 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
463 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
465 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
466 G_CALLBACK (msg_body_focus), obj);
467 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
468 G_CALLBACK (msg_body_focus), obj);
469 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
470 "changed", G_CALLBACK (recpt_field_changed), obj);
471 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
472 "changed", G_CALLBACK (recpt_field_changed), obj);
473 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
474 "changed", G_CALLBACK (recpt_field_changed), obj);
475 recpt_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
476 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
478 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
479 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
481 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
482 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
483 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
484 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
486 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
488 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
489 frame = gtk_frame_new (NULL);
490 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
492 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
493 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
494 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
496 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL)) {
497 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
498 gtk_widget_hide (priv->cc_caption);
500 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL)) {
501 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
502 gtk_widget_hide (priv->bcc_caption);
505 window_box = gtk_vbox_new (FALSE, 0);
506 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
507 gtk_box_pack_end (GTK_BOX (window_box), priv->find_toolbar, FALSE, FALSE, 0);
508 gtk_container_add (GTK_CONTAINER(obj), window_box);
509 priv->scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
510 gtk_container_add (GTK_CONTAINER (frame), priv->scroll_area);
512 gtk_container_set_focus_vadjustment (GTK_CONTAINER (priv->scroll_area),
513 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
515 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
516 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
522 modest_msg_edit_window_finalize (GObject *obj)
524 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
526 if (priv->clipboard_change_handler_id > 0) {
527 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), priv->clipboard_change_handler_id);
528 priv->clipboard_change_handler_id = 0;
531 if (priv->draft_msg != NULL) {
532 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
533 if (TNY_IS_HEADER (header)) {
534 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
535 modest_window_mgr_unregister_header (mgr, header);
537 g_object_unref (priv->draft_msg);
538 priv->draft_msg = NULL;
541 /* This had to stay alive for as long as the combobox that used it: */
542 modest_pair_list_free (priv->from_field_protos);
544 G_OBJECT_CLASS(parent_class)->finalize (obj);
548 menubar_to_menu (GtkUIManager *ui_manager)
550 GtkWidget *main_menu;
554 /* Create new main menu */
555 main_menu = gtk_menu_new();
557 /* Get the menubar from the UI manager */
558 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
560 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
564 menu = GTK_WIDGET (iter->data);
565 gtk_widget_reparent(menu, main_menu);
567 iter = g_list_next (iter);
574 set_msg (ModestMsgEditWindow *self, TnyMsg *msg)
577 const gchar *to, *cc, *bcc, *subject;
579 ModestMsgEditWindowPrivate *priv;
581 TnyHeaderFlags priority_flags;
582 TnyFolder *msg_folder;
584 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
585 g_return_if_fail (TNY_IS_MSG (msg));
587 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
589 header = tny_msg_get_header (msg);
590 to = tny_header_get_to (header);
591 cc = tny_header_get_cc (header);
592 bcc = tny_header_get_bcc (header);
593 subject = tny_header_get_subject (header);
594 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
597 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
599 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
600 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
601 gtk_widget_show (priv->cc_caption);
602 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
603 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
604 gtk_widget_hide (priv->cc_caption);
607 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
608 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
609 gtk_widget_show (priv->bcc_caption);
610 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
611 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
612 gtk_widget_hide (priv->bcc_caption);
615 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
616 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
619 update_window_title (self);
621 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
622 body = modest_tny_msg_get_body (msg, TRUE);
624 if ((body == NULL)||(body[0] == '\0')) {
626 body = modest_text_utils_convert_to_html ("");
628 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
629 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
632 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
635 /* Get the default format required from configuration */
636 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
637 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
640 /* Set the default focus depending on having already a To: field or not */
641 if ((!to)||(*to == '\0')) {
642 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
644 gtk_widget_grab_focus (priv->msg_body);
647 /* TODO: lower priority, select in the From: combo to the
648 value that comes from msg <- not sure, should it be
651 /* Add attachments to the view */
652 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
653 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
654 if (priv->attachments == NULL) {
655 gtk_widget_hide (priv->attachments_caption);
657 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
658 gtk_widget_show_all (priv->attachments_caption);
661 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
662 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
664 reset_modified (self);
666 update_dimmed (self);
667 text_buffer_can_undo (priv->text_buffer, FALSE, self);
668 text_buffer_can_redo (priv->text_buffer, FALSE, self);
670 /* we should set a reference to the incoming message if it is a draft */
671 msg_folder = tny_msg_get_folder (msg);
673 if (modest_tny_folder_is_local_folder (msg_folder) &&
674 modest_tny_folder_get_local_folder_type (msg_folder) == TNY_FOLDER_TYPE_DRAFTS)
675 priv->draft_msg = g_object_ref(msg);
676 g_object_unref (msg_folder);
681 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
684 GList *item_children, *node;
685 GtkWidget *bin_child;
687 bin_child = gtk_bin_get_child (GTK_BIN(item));
689 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
691 for (node = item_children; node != NULL; node = g_list_next (node)) {
692 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
693 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
696 g_list_free (item_children);
700 menu_tool_button_dont_expand (GtkMenuToolButton *item)
703 GList *item_children, *node;
705 box = gtk_bin_get_child (GTK_BIN (item));
706 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
707 item_children = gtk_container_get_children (GTK_CONTAINER (box));
709 for (node = item_children; node != NULL; node = g_list_next (node)) {
710 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
711 if (GTK_IS_TOGGLE_BUTTON (node->data))
712 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
713 else if (GTK_IS_BUTTON (node->data))
714 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
716 g_list_free (item_children);
721 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
723 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
724 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
725 GtkWidget *placeholder;
726 GtkWidget *tool_item;
731 GtkWidget *sizes_menu;
732 GtkWidget *fonts_menu;
733 GSList *radio_group = NULL;
738 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
739 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
741 /* should we hide the toolbar? */
742 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
743 gtk_widget_hide (parent_priv->toolbar);
745 /* Font color placeholder */
746 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
747 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
750 tool_item = GTK_WIDGET (gtk_tool_item_new ());
751 priv->font_color_button = hildon_color_button_new ();
752 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
753 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
754 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
755 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
756 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
757 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
758 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
760 /* Font size and face placeholder */
761 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
762 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
764 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
765 priv->size_tool_button_label = gtk_label_new (NULL);
766 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
767 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
768 size_text,"</span>", NULL);
769 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
771 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
772 sizes_menu = gtk_menu_new ();
773 priv->size_items_group = NULL;
775 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
776 GtkWidget *size_menu_item;
778 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
779 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
780 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
781 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
782 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
783 gtk_widget_show (size_menu_item);
785 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
789 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
790 GtkWidget *item = (GtkWidget *) node->data;
791 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
795 priv->size_items_group = g_slist_reverse (priv->size_items_group);
796 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
797 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
798 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
799 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
800 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
801 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
802 priv->font_size_toolitem = tool_item;
805 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
806 priv->font_tool_button_label = gtk_label_new (NULL);
807 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
808 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
810 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
811 fonts_menu = gtk_menu_new ();
812 priv->font_items_group = NULL;
814 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
815 GtkWidget *font_menu_item;
816 GtkWidget *child_label;
818 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
819 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
820 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
821 wp_get_font_name (font_index), "</span>", NULL);
822 gtk_label_set_markup (GTK_LABEL (child_label), markup);
825 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
826 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
827 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
828 gtk_widget_show (font_menu_item);
830 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
833 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
834 GtkWidget *item = (GtkWidget *) node->data;
835 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
838 priv->font_items_group = g_slist_reverse (priv->font_items_group);
839 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
840 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
841 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
842 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
843 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
844 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
845 priv->font_face_toolitem = tool_item;
847 /* Set expand and homogeneous for remaining items */
848 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
849 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
850 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
851 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
852 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
853 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
854 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
855 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
856 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
864 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name)
867 ModestWindowPrivate *parent_priv;
868 ModestMsgEditWindowPrivate *priv;
869 GtkActionGroup *action_group;
870 GError *error = NULL;
871 GdkPixbuf *window_icon = NULL;
874 gboolean prefer_formatted;
876 ModestPair *account_pair = NULL;
878 g_return_val_if_fail (msg, NULL);
879 g_return_val_if_fail (account_name, NULL);
881 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
883 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
884 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
886 parent_priv->ui_manager = gtk_ui_manager_new();
887 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
888 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
890 /* Add common actions */
891 gtk_action_group_add_actions (action_group,
892 modest_msg_edit_action_entries,
893 G_N_ELEMENTS (modest_msg_edit_action_entries),
895 gtk_action_group_add_toggle_actions (action_group,
896 modest_msg_edit_toggle_action_entries,
897 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
899 gtk_action_group_add_radio_actions (action_group,
900 modest_msg_edit_alignment_radio_action_entries,
901 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
903 G_CALLBACK (modest_ui_actions_on_change_justify),
905 gtk_action_group_add_radio_actions (action_group,
906 modest_msg_edit_zoom_action_entries,
907 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
909 G_CALLBACK (modest_ui_actions_on_change_zoom),
911 gtk_action_group_add_radio_actions (action_group,
912 modest_msg_edit_priority_action_entries,
913 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
915 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
917 gtk_action_group_add_radio_actions (action_group,
918 modest_msg_edit_file_format_action_entries,
919 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
920 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
921 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
923 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
924 g_object_unref (action_group);
926 /* Load the UI definition */
927 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
930 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
931 g_clear_error (&error);
934 /* Add accelerators */
935 gtk_window_add_accel_group (GTK_WINDOW (obj),
936 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
939 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
940 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
943 init_window (MODEST_MSG_EDIT_WINDOW(obj));
945 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
947 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
949 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
951 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
953 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
954 if (account_pair != NULL)
955 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
957 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg);
959 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
961 /* Set window icon */
962 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
964 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
965 g_object_unref (window_icon);
968 /* Dim at start clipboard actions */
969 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
970 gtk_action_set_sensitive (action, FALSE);
971 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
972 gtk_action_set_sensitive (action, FALSE);
973 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
974 gtk_action_set_sensitive (action, FALSE);
976 /* Update select all */
977 update_select_all_dimming (MODEST_MSG_EDIT_WINDOW (obj));
978 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu");
979 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (edit_menu_activated), obj);
980 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu");
981 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (view_menu_activated), obj);
983 /* set initial state of cc and bcc */
984 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
985 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
986 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
987 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
988 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
989 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
991 /* Setup the file format */
992 conf = modest_runtime_get_conf ();
993 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
995 g_clear_error (&error);
996 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
998 file_format = (prefer_formatted) ?
999 MODEST_FILE_FORMAT_FORMATTED_TEXT :
1000 MODEST_FILE_FORMAT_PLAIN_TEXT;
1001 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
1003 update_paste_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1005 return (ModestWindow*) obj;
1009 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1011 GString **string_buffer = (GString **) user_data;
1013 *string_buffer = g_string_append (*string_buffer, buffer);
1019 * @result: A new string which should be freed with g_free().
1022 get_formatted_data (ModestMsgEditWindow *edit_window)
1024 ModestMsgEditWindowPrivate *priv;
1025 GString *string_buffer = g_string_new ("");
1027 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1029 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1031 return g_string_free (string_buffer, FALSE);
1036 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1039 const gchar *account_name;
1040 ModestMsgEditWindowPrivate *priv;
1042 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1044 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1046 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1047 g_return_val_if_fail (account_name, NULL);
1050 /* don't free these (except from) */
1051 data = g_slice_new0 (MsgData);
1052 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1054 data->account_name = g_strdup (account_name);
1055 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1056 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1057 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1058 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1059 if (priv->draft_msg) {
1060 data->draft_msg = g_object_ref (priv->draft_msg);
1062 data->draft_msg = NULL;
1065 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1067 gtk_text_buffer_get_bounds (buf, &b, &e);
1068 data->plain_body = g_strdup (gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE)); /* returns a copy */
1070 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1071 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1073 data->html_body = NULL;
1075 /* deep-copy the data */
1076 GList *cursor = priv->attachments;
1077 data->attachments = NULL;
1079 if (!(TNY_IS_MIME_PART(cursor->data))) {
1080 g_warning ("strange data in attachment list");
1081 cursor = g_list_next (cursor);
1084 data->attachments = g_list_append (data->attachments,
1085 g_object_ref (cursor->data));
1086 cursor = g_list_next (cursor);
1089 data->priority_flags = priv->priority_flags;
1096 unref_gobject (GObject *obj, gpointer data)
1098 if (!G_IS_OBJECT(obj))
1100 g_object_unref (obj);
1104 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1107 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1115 g_free (data->subject);
1116 g_free (data->plain_body);
1117 g_free (data->html_body);
1118 g_free (data->account_name);
1120 if (data->draft_msg != NULL) {
1121 g_object_unref (data->draft_msg);
1122 data->draft_msg = NULL;
1125 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1126 g_list_free (data->attachments);
1128 g_slice_free (MsgData, data);
1132 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1135 ModestMsgEditWindowPrivate *priv = NULL;
1136 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1138 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1140 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1142 return MODEST_MSG_EDIT_FORMAT_HTML;
1144 return MODEST_MSG_EDIT_FORMAT_TEXT;
1148 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1149 ModestMsgEditFormat format)
1151 ModestMsgEditWindowPrivate *priv;
1153 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1154 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1157 case MODEST_MSG_EDIT_FORMAT_HTML:
1158 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1160 case MODEST_MSG_EDIT_FORMAT_TEXT:
1161 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1164 g_return_if_reached ();
1168 ModestMsgEditFormatState *
1169 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1171 ModestMsgEditFormatState *format_state = NULL;
1172 ModestMsgEditWindowPrivate *priv;
1173 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1175 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1176 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1178 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1180 format_state = g_new0 (ModestMsgEditFormatState, 1);
1181 format_state->bold = buffer_format->bold&0x1;
1182 format_state->italics = buffer_format->italic&0x1;
1183 format_state->bullet = buffer_format->bullet&0x1;
1184 format_state->color = buffer_format->color;
1185 format_state->font_size = buffer_format->font_size;
1186 format_state->font_family = wp_get_font_name (buffer_format->font);
1187 format_state->justification = buffer_format->justification;
1188 g_free (buffer_format);
1190 return format_state;
1195 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1196 const ModestMsgEditFormatState *format_state)
1198 ModestMsgEditWindowPrivate *priv;
1199 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1200 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1201 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1202 g_return_if_fail (format_state != NULL);
1204 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1205 gtk_widget_grab_focus (priv->msg_body);
1206 buffer_format->bold = (format_state->bold != FALSE);
1207 buffer_format->italic = (format_state->italics != FALSE);
1208 buffer_format->color = format_state->color;
1209 buffer_format->font_size = format_state->font_size;
1210 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1211 buffer_format->justification = format_state->justification;
1212 buffer_format->bullet = format_state->bullet;
1214 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1216 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1217 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1218 buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
1219 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1220 buffer_format->cs.font = (buffer_format->font != current_format->font);
1221 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1222 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1224 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1225 if (buffer_format->cs.bold) {
1226 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1228 if (buffer_format->cs.italic) {
1229 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1231 if (buffer_format->cs.color) {
1232 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1234 if (buffer_format->cs.font_size) {
1235 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1237 if (buffer_format->cs.justification) {
1238 switch (buffer_format->justification) {
1239 case GTK_JUSTIFY_LEFT:
1240 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1242 case GTK_JUSTIFY_CENTER:
1243 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1245 case GTK_JUSTIFY_RIGHT:
1246 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1253 if (buffer_format->cs.font) {
1254 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1256 if (buffer_format->cs.bullet) {
1257 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((int)buffer_format->bullet));
1259 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1260 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1262 g_free (current_format);
1267 toggle_action_set_active_block_notify (GtkToggleAction *action,
1270 GSList *proxies = NULL;
1272 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1273 proxies != NULL; proxies = g_slist_next (proxies)) {
1274 GtkWidget *widget = (GtkWidget *) proxies->data;
1275 gtk_action_block_activate_from (GTK_ACTION (action), widget);
1278 gtk_toggle_action_set_active (action, value);
1280 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1281 proxies != NULL; proxies = g_slist_next (proxies)) {
1282 GtkWidget *widget = (GtkWidget *) proxies->data;
1283 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
1288 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1290 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1292 ModestWindowPrivate *parent_priv;
1293 ModestMsgEditWindowPrivate *priv;
1294 GtkWidget *new_size_menuitem;
1295 GtkWidget *new_font_menuitem;
1297 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1298 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1300 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1301 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1302 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1303 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1305 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1306 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1307 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1310 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1312 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1313 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1315 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1316 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1318 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1319 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1321 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1322 G_CALLBACK (modest_msg_edit_window_color_button_change),
1324 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1325 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1326 G_CALLBACK (modest_msg_edit_window_color_button_change),
1329 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1330 buffer_format->font_size))->data);
1331 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1335 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1336 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1337 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1339 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1340 G_CALLBACK (modest_msg_edit_window_size_change),
1342 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1343 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1344 G_CALLBACK (modest_msg_edit_window_size_change),
1348 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1349 buffer_format->font))->data);
1350 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1354 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1355 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1356 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1358 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1359 G_CALLBACK (modest_msg_edit_window_font_change),
1361 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1362 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1363 G_CALLBACK (modest_msg_edit_window_font_change),
1367 g_free (buffer_format);
1373 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1376 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1377 ModestMsgEditWindowPrivate *priv;
1378 GtkWidget *dialog = NULL;
1380 const GdkColor *new_color = NULL;
1382 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1383 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1385 #ifdef MODEST_HILDON_VERSION_0
1386 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1387 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1389 dialog = hildon_color_chooser_new ();
1390 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1391 #endif /*MODEST_HILDON_VERSION_0*/
1392 g_free (buffer_format);
1394 response = gtk_dialog_run (GTK_DIALOG (dialog));
1396 case GTK_RESPONSE_OK: {
1397 #ifdef MODEST_HILDON_VERSION_0
1398 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1401 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1403 #endif /*MODEST_HILDON_VERSION_0*/
1410 gtk_widget_destroy (dialog);
1412 if (new_color != NULL)
1413 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1418 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1421 ModestMsgEditWindowPrivate *priv;
1422 GtkWidget *dialog = NULL;
1424 GdkColor *old_color = NULL;
1425 const GdkColor *new_color = NULL;
1427 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1428 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1430 #ifdef MODEST_HILDON_VERSION_0
1431 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1432 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1434 dialog = hildon_color_chooser_new ();
1435 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1436 #endif /*MODEST_HILDON_VERSION_9*/
1438 response = gtk_dialog_run (GTK_DIALOG (dialog));
1440 case GTK_RESPONSE_OK: {
1441 #ifdef MODEST_HILDON_VERSION_0
1442 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1445 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1447 #endif /*MODEST_HILDON_VERSION_0*/
1453 gtk_widget_destroy (dialog);
1455 if (new_color != NULL)
1456 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1462 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1465 ModestMsgEditWindowPrivate *priv;
1466 GtkWidget *dialog = NULL;
1468 GSList *uris = NULL;
1469 GSList *uri_node = NULL;
1471 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1473 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1474 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1475 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1477 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1479 response = gtk_dialog_run (GTK_DIALOG (dialog));
1481 case GTK_RESPONSE_OK:
1482 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1487 gtk_widget_destroy (dialog);
1489 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1491 GnomeVFSHandle *handle = NULL;
1492 GnomeVFSResult result;
1493 GtkTextIter position;
1494 GtkTextMark *insert_mark;
1496 uri = (const gchar *) uri_node->data;
1497 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1498 if (result == GNOME_VFS_OK) {
1499 GdkPixbufLoader *loader;
1501 GnomeVFSFileInfo info;
1502 gchar *filename, *basename, *escaped_filename;
1503 TnyMimePart *mime_part;
1506 const gchar *mime_type = NULL;
1507 GnomeVFSURI *vfs_uri;
1509 vfs_uri = gnome_vfs_uri_new (uri);
1511 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1512 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1513 g_free (escaped_filename);
1514 gnome_vfs_uri_unref (vfs_uri);
1516 if (gnome_vfs_get_file_info (uri, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
1517 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1519 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1521 mime_part = tny_platform_factory_new_mime_part
1522 (modest_runtime_get_platform_factory ());
1523 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1525 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1527 content_id = g_strdup_printf ("%d", priv->last_cid);
1528 tny_mime_part_set_content_id (mime_part, content_id);
1529 g_free (content_id);
1532 basename = g_path_get_basename (filename);
1533 tny_mime_part_set_filename (mime_part, basename);
1536 tny_stream_reset (TNY_STREAM (stream));
1537 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1538 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1539 unsigned char read_buffer[128];
1541 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1542 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
1545 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1546 g_object_ref (pixbuf);
1547 gdk_pixbuf_loader_close (loader, NULL);
1548 g_object_unref (loader);
1550 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1551 GdkPixbuf *new_pixbuf;
1553 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1554 gdk_pixbuf_get_width (pixbuf);
1555 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1556 g_object_unref (pixbuf);
1557 pixbuf = new_pixbuf;
1560 if (pixbuf != NULL) {
1561 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1562 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1563 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1566 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1567 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1569 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1570 gtk_widget_show_all (priv->attachments_caption);
1571 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1581 modest_msg_edit_window_attach_file (ModestMsgEditWindow *window)
1584 ModestMsgEditWindowPrivate *priv;
1585 GtkWidget *dialog = NULL;
1587 GSList *uris = NULL;
1590 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1592 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1593 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
1594 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1596 response = gtk_dialog_run (GTK_DIALOG (dialog));
1598 case GTK_RESPONSE_OK:
1599 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1604 gtk_widget_destroy (dialog);
1606 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1608 GnomeVFSHandle *handle = NULL;
1609 GnomeVFSResult result;
1611 uri = (const gchar *) uri_node->data;
1612 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1613 if (result == GNOME_VFS_OK) {
1614 TnyMimePart *mime_part;
1616 const gchar *mime_type = NULL;
1618 gchar *escaped_filename;
1621 GnomeVFSFileInfo info;
1622 GnomeVFSURI *vfs_uri;
1624 vfs_uri = gnome_vfs_uri_new (uri);
1627 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1628 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1629 g_free (escaped_filename);
1630 gnome_vfs_uri_unref (vfs_uri);
1632 if (gnome_vfs_get_file_info (uri,
1634 GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
1635 GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1637 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1638 mime_part = tny_platform_factory_new_mime_part
1639 (modest_runtime_get_platform_factory ());
1640 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1642 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1644 content_id = g_strdup_printf ("%d", priv->last_cid);
1645 tny_mime_part_set_content_id (mime_part, content_id);
1646 g_free (content_id);
1649 basename = g_path_get_basename (filename);
1650 tny_mime_part_set_filename (mime_part, basename);
1653 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1654 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1656 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1657 gtk_widget_show_all (priv->attachments_caption);
1658 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1663 g_slist_foreach (uris, (GFunc) g_free, NULL);
1664 g_slist_free (uris);
1668 modest_msg_edit_window_attach_file_noninteractive (
1669 ModestMsgEditWindow *window,
1670 const gchar *file_uri)
1673 ModestMsgEditWindowPrivate *priv;
1675 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1677 if (file_uri && strlen(file_uri)) {
1680 /* TODO: We should probably try to use only the URI,
1681 * instead of using a filename.
1683 gchar* filename = g_filename_from_uri (file_uri, NULL, NULL);
1685 g_warning("%s: g_filename_from_uri('%s') failed.\n", __FUNCTION__, file_uri);
1688 file_id = g_open (filename, O_RDONLY, 0);
1689 if (file_id != -1) {
1690 TnyMimePart *mime_part;
1692 const gchar *mime_type;
1695 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1696 mime_type = gnome_vfs_get_mime_type(filename);
1698 mime_type = gnome_vfs_get_file_mime_type_fast (filename, NULL);
1700 mime_part = tny_platform_factory_new_mime_part
1701 (modest_runtime_get_platform_factory ());
1702 stream = TNY_STREAM (tny_fs_stream_new (file_id));
1704 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1706 content_id = g_strdup_printf ("%d", priv->last_cid);
1707 tny_mime_part_set_content_id (mime_part, content_id);
1708 g_free (content_id);
1711 basename = g_path_get_basename (filename);
1712 tny_mime_part_set_filename (mime_part, basename);
1715 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1716 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1718 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1719 gtk_widget_show_all (priv->attachments_caption);
1720 } else if (file_id == -1) {
1722 g_warning("file to be attached does not exist: %s", filename);
1730 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1733 ModestMsgEditWindowPrivate *priv;
1734 gboolean clean_list = FALSE;
1736 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1737 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1739 if (att_list == NULL) {
1740 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1744 if (att_list == NULL) {
1745 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1747 GtkWidget *confirmation_dialog = NULL;
1748 gboolean dialog_response;
1750 gchar *message = NULL;
1751 const gchar *filename = NULL;
1753 if (att_list->next == NULL) {
1754 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1758 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1759 att_list->next == NULL), filename);
1760 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1762 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1763 gtk_widget_destroy (confirmation_dialog);
1764 if (!dialog_response) {
1766 g_list_free (att_list);
1769 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1771 for (node = att_list; node != NULL; node = g_list_next (node)) {
1772 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1773 const gchar *att_id;
1774 priv->attachments = g_list_remove (priv->attachments, mime_part);
1776 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1778 if (priv->attachments == NULL)
1779 gtk_widget_hide (priv->attachments_caption);
1780 att_id = tny_mime_part_get_content_id (mime_part);
1782 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1784 g_object_unref (mime_part);
1785 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1790 g_list_free (att_list);
1794 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1797 ModestMsgEditWindowPrivate *priv;
1798 GdkColor *new_color;
1799 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1801 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1802 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1805 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1807 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1809 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1811 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1816 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1819 ModestMsgEditWindowPrivate *priv;
1820 gint new_size_index;
1821 ModestMsgEditWindow *window;
1824 window = MODEST_MSG_EDIT_WINDOW (userdata);
1825 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1826 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1828 if (gtk_check_menu_item_get_active (menu_item)) {
1830 WPTextBufferFormat format;
1832 memset (&format, 0, sizeof (format));
1833 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1835 label = gtk_bin_get_child (GTK_BIN (menu_item));
1837 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1838 format.cs.font_size = TRUE;
1839 format.cs.text_position = TRUE;
1840 format.cs.font = TRUE;
1841 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1842 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1844 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1845 (gpointer) wp_get_font_size_index (new_size_index, 12)))
1846 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1848 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1849 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1850 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1856 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1859 ModestMsgEditWindowPrivate *priv;
1860 gint new_font_index;
1861 ModestMsgEditWindow *window;
1864 window = MODEST_MSG_EDIT_WINDOW (userdata);
1865 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1866 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1868 if (gtk_check_menu_item_get_active (menu_item)) {
1871 label = gtk_bin_get_child (GTK_BIN (menu_item));
1873 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1875 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1876 (gpointer) new_font_index))
1877 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1879 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1880 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1881 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1887 modest_msg_edit_window_set_zoom (ModestWindow *window,
1890 ModestMsgEditWindowPrivate *priv;
1891 ModestWindowPrivate *parent_priv;
1892 GtkRadioAction *zoom_radio_action;
1894 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1896 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1897 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1898 priv->zoom_level = zoom;
1899 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom*DEFAULT_FONT_SCALE);
1901 /* Zoom level menu options should be updated with the current zoom level */
1902 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1903 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1904 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1905 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1906 /* FIXME: Not availible before Gtk 2.10 */
1908 gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
1913 modest_msg_edit_window_get_zoom (ModestWindow *window)
1915 ModestMsgEditWindowPrivate *priv;
1917 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1919 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1920 return priv->zoom_level;
1924 zoom_allowed (ModestMsgEditWindow *window)
1928 focus = gtk_window_get_focus (GTK_WINDOW (window));
1929 return (focus != NULL && WP_IS_TEXT_VIEW (focus));
1933 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1935 ModestWindowPrivate *parent_priv;
1936 GtkRadioAction *zoom_radio_action;
1937 GSList *group, *node;
1939 /* First we check if the text view is focused. If not, zooming is not allowed */
1940 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1941 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1945 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1946 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1947 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1949 group = gtk_radio_action_get_group (zoom_radio_action);
1951 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1952 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
1956 for (node = group; node != NULL; node = g_slist_next (node)) {
1957 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1958 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1966 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1968 ModestWindowPrivate *parent_priv;
1969 GtkRadioAction *zoom_radio_action;
1970 GSList *group, *node;
1972 /* First we check if the text view is focused. If not, zooming is not allowed */
1973 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1974 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1978 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1979 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1980 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1982 group = gtk_radio_action_get_group (zoom_radio_action);
1984 for (node = group; node != NULL; node = g_slist_next (node)) {
1985 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1986 if (node->next != NULL) {
1987 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1990 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
1998 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2000 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2001 ModestWindowPrivate *parent_priv;
2002 ModestWindowMgr *mgr;
2003 gboolean is_fullscreen;
2004 GtkAction *fs_toggle_action;
2007 mgr = modest_runtime_get_window_mgr ();
2008 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2010 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2012 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2013 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2014 if (is_fullscreen != active)
2015 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2023 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
2025 ModestWindowPrivate *parent_priv;
2026 GtkAction *fs_toggle_action;
2029 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2031 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2032 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
2033 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
2037 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2040 ModestMsgEditWindowPrivate *priv = NULL;
2041 const gchar *recipients;
2042 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2044 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2045 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2046 recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field));
2047 if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2048 gtk_widget_show (priv->cc_caption);
2050 gtk_widget_hide (priv->cc_caption);
2051 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2055 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2058 ModestMsgEditWindowPrivate *priv = NULL;
2059 const gchar *recipients;
2060 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2062 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2063 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2064 recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field));
2065 if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2066 gtk_widget_show (priv->bcc_caption);
2068 gtk_widget_hide (priv->bcc_caption);
2069 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2073 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2074 ModestRecptEditor *editor)
2076 ModestMsgEditWindowPrivate *priv;
2078 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2079 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2080 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2082 if (editor == NULL) {
2083 GtkWidget *view_focus;
2084 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2086 /* This code should be kept in sync with ModestRecptEditor. The
2087 textview inside the recpt editor is the one that really gets the
2088 focus. As it's inside a scrolled window, and this one inside the
2089 hbox recpt editor inherits from, we'll need to go up in the
2090 hierarchy to know if the text view is part of the recpt editor
2091 or if it's a different text entry */
2093 if (gtk_widget_get_parent (view_focus)) {
2094 GtkWidget *first_parent;
2096 first_parent = gtk_widget_get_parent (view_focus);
2097 if (gtk_widget_get_parent (first_parent) &&
2098 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2099 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2104 editor = MODEST_RECPT_EDITOR (priv->to_field);
2108 modest_address_book_select_addresses (editor);
2113 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2115 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2117 modest_msg_edit_window_open_addressbook (window, NULL);
2121 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2122 gboolean show_toolbar)
2124 ModestWindowPrivate *parent_priv;
2126 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2127 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2129 /* FIXME: we can not just use the code of
2130 modest_msg_edit_window_setup_toolbar because it has a
2131 mixture of both initialization and creation code. */
2134 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2136 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2140 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2141 TnyHeaderFlags priority_flags)
2143 ModestMsgEditWindowPrivate *priv;
2144 ModestWindowPrivate *parent_priv;
2146 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2148 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2149 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2150 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2152 if (priv->priority_flags != priority_flags) {
2153 GtkAction *priority_action = NULL;
2155 priv->priority_flags = priority_flags;
2157 switch (priority_flags) {
2158 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2159 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2160 gtk_widget_show (priv->priority_icon);
2161 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2162 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2164 case TNY_HEADER_FLAG_LOW_PRIORITY:
2165 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2166 gtk_widget_show (priv->priority_icon);
2167 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2168 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2171 gtk_widget_hide (priv->priority_icon);
2172 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2173 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2176 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2177 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2182 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2185 ModestMsgEditWindowPrivate *priv;
2186 ModestWindowPrivate *parent_priv;
2187 gint current_format;
2189 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2191 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2192 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2194 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2195 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2197 if (current_format != file_format) {
2198 switch (file_format) {
2199 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2200 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2202 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2206 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2207 response = gtk_dialog_run (GTK_DIALOG (dialog));
2208 gtk_widget_destroy (dialog);
2209 if (response == GTK_RESPONSE_OK) {
2210 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2212 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2213 toggle_action_set_active_block_notify (action, TRUE);
2218 update_dimmed (window);
2223 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2226 ModestMsgEditWindowPrivate *priv;
2227 WPTextBufferFormat oldfmt, fmt;
2228 gint old_position = 0;
2232 GdkColor *color = NULL;
2233 gboolean bold, bold_set, italic, italic_set;
2234 gboolean underline, underline_set;
2235 gboolean strikethrough, strikethrough_set;
2236 gboolean position_set;
2237 gboolean font_size_set, font_set, color_set;
2240 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2241 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2243 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2245 /* First we get the currently selected font information */
2246 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2247 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2249 switch (oldfmt.text_position) {
2250 case TEXT_POSITION_NORMAL:
2253 case TEXT_POSITION_SUPERSCRIPT:
2261 g_object_set (G_OBJECT (dialog),
2262 "bold", oldfmt.bold != FALSE,
2263 "bold-set", !oldfmt.cs.bold,
2264 "underline", oldfmt.underline != FALSE,
2265 "underline-set", !oldfmt.cs.underline,
2266 "italic", oldfmt.italic != FALSE,
2267 "italic-set", !oldfmt.cs.italic,
2268 "strikethrough", oldfmt.strikethrough != FALSE,
2269 "strikethrough-set", !oldfmt.cs.strikethrough,
2270 "color", &oldfmt.color,
2271 "color-set", !oldfmt.cs.color,
2272 "size", wp_font_size[oldfmt.font_size],
2273 "size-set", !oldfmt.cs.font_size,
2274 "position", old_position,
2275 "position-set", !oldfmt.cs.text_position,
2276 "family", wp_get_font_name (oldfmt.font),
2277 "family-set", !oldfmt.cs.font,
2280 gtk_widget_show_all (dialog);
2281 response = gtk_dialog_run (GTK_DIALOG (dialog));
2282 if (response == GTK_RESPONSE_OK) {
2284 g_object_get( dialog,
2286 "bold-set", &bold_set,
2287 "underline", &underline,
2288 "underline-set", &underline_set,
2290 "italic-set", &italic_set,
2291 "strikethrough", &strikethrough,
2292 "strikethrough-set", &strikethrough_set,
2294 "color-set", &color_set,
2296 "size-set", &font_size_set,
2297 "family", &font_name,
2298 "family-set", &font_set,
2299 "position", &position,
2300 "position-set", &position_set,
2305 if (response == GTK_RESPONSE_OK) {
2306 memset(&fmt, 0, sizeof(fmt));
2312 fmt.italic = italic;
2313 fmt.cs.italic = TRUE;
2315 if (underline_set) {
2316 fmt.underline = underline;
2317 fmt.cs.underline = TRUE;
2319 if (strikethrough_set) {
2320 fmt.strikethrough = strikethrough;
2321 fmt.cs.strikethrough = TRUE;
2326 ? TEXT_POSITION_NORMAL
2327 : ( ( position == 1 )
2328 ? TEXT_POSITION_SUPERSCRIPT
2329 : TEXT_POSITION_SUBSCRIPT );
2330 fmt.cs.text_position = TRUE;
2334 fmt.cs.color = TRUE;
2337 fmt.font = wp_get_font_index(font_name,
2342 if (font_size_set) {
2343 fmt.font_size = wp_get_font_size_index(
2344 font_size, DEFAULT_FONT_SIZE);
2345 fmt.cs.font_size = TRUE;
2347 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2349 gtk_widget_destroy (dialog);
2351 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2355 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2357 ModestMsgEditWindowPrivate *priv;
2359 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2360 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2362 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2364 update_dimmed (window);
2369 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2371 ModestMsgEditWindowPrivate *priv;
2373 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2374 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2376 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2378 update_dimmed (window);
2383 update_dimmed (ModestMsgEditWindow *window)
2385 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2386 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2390 gboolean editor_focused;
2392 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2393 editor_focused = gtk_widget_is_focus (priv->msg_body);
2395 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2396 gtk_action_set_sensitive (action, rich_text && editor_focused);
2397 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2398 gtk_action_set_sensitive (action, rich_text && editor_focused);
2399 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2400 gtk_action_set_sensitive (action, rich_text && editor_focused);
2401 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2402 gtk_action_set_sensitive (action, rich_text && editor_focused);
2403 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2404 gtk_action_set_sensitive (action, rich_text && editor_focused);
2405 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2406 gtk_action_set_sensitive (action, rich_text && editor_focused);
2407 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2408 gtk_action_set_sensitive (action, rich_text && editor_focused);
2409 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2410 gtk_action_set_sensitive (action, rich_text && editor_focused);
2411 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2412 gtk_action_set_sensitive (action, rich_text && editor_focused);
2413 widget = priv->font_color_button;
2414 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2415 widget = priv->font_size_toolitem;
2416 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2417 widget = priv->font_face_toolitem;
2418 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2422 setup_insensitive_handlers (ModestMsgEditWindow *window)
2424 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2425 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2428 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2429 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2430 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2431 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2432 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2433 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2434 widget = priv->font_color_button;
2435 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2436 widget = priv->font_size_toolitem;
2437 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2438 widget = priv->font_face_toolitem;
2439 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2444 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2446 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2449 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2450 gtk_action_set_sensitive (action, can_undo);
2454 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2456 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2459 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/RedoMenu");
2460 gtk_action_set_sensitive (action, can_redo);
2464 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2467 GtkTextIter match_start, match_end;
2469 if (image_id == NULL)
2472 gtk_text_buffer_get_start_iter (buffer, &iter);
2474 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2475 GSList *tags = gtk_text_iter_get_tags (&match_start);
2477 for (node = tags; node != NULL; node = g_slist_next (node)) {
2478 GtkTextTag *tag = (GtkTextTag *) node->data;
2479 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2480 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2481 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2483 offset = gtk_text_iter_get_offset (&match_start);
2484 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2485 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2489 gtk_text_iter_forward_char (&iter);
2494 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2496 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2497 GtkTextIter real_start, real_end;
2498 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2500 if (gtk_text_iter_compare (start, end) > 0) {
2504 real_start = *start;
2508 GSList *tags = gtk_text_iter_get_tags (&real_start);
2510 for (node = tags; node != NULL; node = g_slist_next (node)) {
2511 GtkTextTag *tag = (GtkTextTag *) node->data;
2512 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2513 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2515 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2517 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2520 } while (gtk_text_iter_forward_char (&real_start)&&
2521 (gtk_text_iter_compare (&real_start, &real_end)<=0));
2525 msg_body_focus (GtkWidget *focus,
2526 GdkEventFocus *event,
2530 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2535 recpt_field_changed (GtkTextBuffer *buffer,
2536 ModestMsgEditWindow *editor)
2538 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2539 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2540 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2541 gboolean dim = FALSE;
2544 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2545 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2546 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2548 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2549 gtk_text_buffer_get_char_count (cc_buffer) +
2550 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2552 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2553 gtk_action_set_sensitive (action, !dim);
2554 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2555 gtk_action_set_sensitive (action, !dim);
2559 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2561 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2565 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2567 gboolean rich_text, editor_focused;
2569 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2570 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2571 editor_focused = gtk_widget_is_focus (priv->msg_body);
2574 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2575 else if (!editor_focused)
2576 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2580 reset_modified (ModestMsgEditWindow *editor)
2582 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2583 GtkTextBuffer *buffer;
2585 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2586 gtk_text_buffer_set_modified (buffer, FALSE);
2587 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2588 gtk_text_buffer_set_modified (buffer, FALSE);
2589 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2590 gtk_text_buffer_set_modified (buffer, FALSE);
2591 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2595 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2597 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2598 GtkTextBuffer *buffer;
2600 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2601 if (gtk_text_buffer_get_modified (buffer))
2603 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2604 if (gtk_text_buffer_get_modified (buffer))
2606 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2607 if (gtk_text_buffer_get_modified (buffer))
2609 if (gtk_text_buffer_get_modified (priv->text_buffer))
2616 modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
2618 ModestMsgEditWindowPrivate *priv = NULL;
2620 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2621 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2623 /* check if there's no recipient added */
2624 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2625 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2626 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2627 /* no recipient contents, then select contacts */
2628 modest_msg_edit_window_open_addressbook (window, NULL);
2632 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
2634 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
2636 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
2639 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2646 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2647 ModestMsgEditWindow *window)
2649 modest_msg_edit_window_attach_file (window);
2653 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2655 ModestMsgEditWindow *window)
2657 ModestWindowPrivate *parent_priv;
2658 ModestMsgEditWindowPrivate *priv;
2660 gboolean has_selection;
2662 GList *selected_attachments = NULL;
2663 gint n_att_selected = 0;
2665 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2666 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2668 if (!GTK_WIDGET_VISIBLE (window))
2670 has_selection = gtk_clipboard_wait_for_targets (clipboard, NULL, NULL);
2671 focused = gtk_window_get_focus (GTK_WINDOW (window));
2673 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2674 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2675 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2676 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2678 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2679 n_att_selected = g_list_length (selected_attachments);
2680 g_list_free (selected_attachments);
2682 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2683 gtk_action_set_sensitive (action, n_att_selected == 1);
2685 update_paste_dimming (window);
2689 update_window_title (ModestMsgEditWindow *window)
2691 ModestMsgEditWindowPrivate *priv = NULL;
2692 const gchar *subject;
2694 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2695 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2696 if (subject == NULL || subject[0] == '\0')
2697 subject = _("mail_va_new_email");
2699 gtk_window_set_title (GTK_WINDOW (window), subject);
2704 subject_field_changed (GtkEditable *editable,
2705 ModestMsgEditWindow *window)
2707 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2708 update_window_title (window);
2709 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2713 message_is_empty (ModestMsgEditWindow *window)
2715 ModestMsgEditWindowPrivate *priv = NULL;
2717 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2718 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2720 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
2721 * so we can ignore markup.
2723 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
2726 count = gtk_text_buffer_get_char_count (buf);
2732 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2735 ModestMsgEditWindowPrivate *priv = NULL;
2737 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2738 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2740 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2742 /* Show a warning if there is nothing to search: */
2743 if (show && message_is_empty (window)) {
2744 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
2749 gtk_widget_show_all (priv->find_toolbar);
2750 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2752 gtk_widget_hide_all (priv->find_toolbar);
2753 gtk_widget_grab_focus (priv->msg_body);
2759 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2761 GtkTextIter *match_start,
2762 GtkTextIter *match_end)
2764 GtkTextIter end_iter;
2765 gchar *str_casefold;
2768 gchar *range_casefold;
2771 gboolean result = FALSE;
2778 gtk_text_iter_forward_to_end (&end_iter);
2780 str_casefold = g_utf8_casefold (str, -1);
2781 str_chars_n = strlen (str);
2783 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2784 range_casefold = g_utf8_casefold (range_text, -1);
2785 range_chars_n = strlen (range_casefold);
2787 if (range_chars_n < str_chars_n) {
2788 g_free (str_casefold);
2789 g_free (range_text);
2790 g_free (range_casefold);
2794 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2795 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2796 if (!g_utf8_collate (range_subtext, str_casefold)) {
2797 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2799 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2800 match_start, match_end, NULL);
2801 g_free (found_text);
2803 g_free (range_subtext);
2807 g_free (str_casefold);
2808 g_free (range_text);
2809 g_free (range_casefold);
2816 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2817 ModestMsgEditWindow *window)
2819 gchar *current_search = NULL;
2820 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2822 GtkTextIter selection_start, selection_end;
2823 GtkTextIter match_start, match_end;
2824 gboolean continue_search = FALSE;
2826 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2827 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2828 g_free (current_search);
2829 g_free (priv->last_search);
2830 priv->last_search = NULL;
2831 /* Information banner about empty search */
2832 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2836 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2837 continue_search = TRUE;
2839 g_free (priv->last_search);
2840 priv->last_search = g_strdup (current_search);
2843 if (continue_search) {
2844 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2845 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2846 &match_start, &match_end);
2848 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2850 GtkTextIter buffer_start;
2851 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2852 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2853 &match_start, &match_end);
2855 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2858 /* Mark as selected the string found in search */
2860 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2861 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2863 g_free (priv->last_search);
2864 priv->last_search = NULL;
2866 g_free (current_search);
2870 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2871 ModestMsgEditWindow *window)
2873 GtkToggleAction *toggle;
2874 ModestWindowPrivate *parent_priv;
2875 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2877 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2878 gtk_toggle_action_set_active (toggle, FALSE);
2883 update_paste_dimming (ModestMsgEditWindow *window)
2885 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2886 GtkAction *action = NULL;
2887 GtkClipboard *clipboard = NULL;
2891 focused = gtk_window_get_focus (GTK_WINDOW (window));
2893 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2894 active = gtk_clipboard_wait_is_text_available (clipboard);
2897 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2901 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2902 gtk_action_set_sensitive (action, active);
2907 update_select_all_dimming (ModestMsgEditWindow *window)
2910 gboolean dimmed = FALSE;
2912 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2914 focused = gtk_window_get_focus (GTK_WINDOW (window));
2915 if (GTK_IS_ENTRY (focused)) {
2916 const gchar *current_text;
2917 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
2918 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
2919 } else if (GTK_IS_TEXT_VIEW (focused)) {
2920 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
2921 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
2922 } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
2925 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
2926 gtk_action_set_sensitive (action, !dimmed);
2930 update_zoom_dimming (ModestMsgEditWindow *window)
2933 gboolean dimmed = FALSE;
2935 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2937 focused = gtk_window_get_focus (GTK_WINDOW (window));
2938 dimmed = ! WP_IS_TEXT_VIEW (focused);
2939 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2940 gtk_action_set_sensitive (action, !dimmed);
2944 edit_menu_activated (GtkAction *action,
2947 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2949 update_select_all_dimming (window);
2950 update_paste_dimming (window);
2953 view_menu_activated (GtkAction *action,
2956 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2958 update_zoom_dimming (window);
2962 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
2964 ModestMsgEditWindowPrivate *priv;
2966 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
2971 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
2974 ModestMsgEditWindowPrivate *priv;
2976 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
2982 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
2985 ModestMsgEditWindowPrivate *priv;
2986 TnyHeader *header = NULL;
2988 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2989 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
2991 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2992 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
2994 if (priv->draft_msg != NULL) {
2995 header = tny_msg_get_header (priv->draft_msg);
2996 if (TNY_IS_HEADER (header)) {
2997 modest_window_mgr_unregister_header (mgr, header);
2999 g_object_unref (priv->draft_msg);
3002 if (draft != NULL) {
3003 g_object_ref (draft);
3004 header = tny_msg_get_header (draft);
3005 if (TNY_IS_HEADER (header))
3006 modest_window_mgr_register_header (mgr, header);
3009 priv->draft_msg = draft;