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);
1460 static TnyStream* create_stream_for_uri (const gchar* uri)
1465 TnyStream *result = NULL;
1467 GnomeVFSHandle *handle = NULL;
1468 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1469 if (test == GNOME_VFS_OK) {
1470 /* Create the tinymail stream: */
1471 /* Presumably tinymai will call gnome_vfs_close (handle) later. */
1472 result = TNY_STREAM (tny_vfs_stream_new (handle));
1479 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1482 ModestMsgEditWindowPrivate *priv;
1483 GtkWidget *dialog = NULL;
1485 GSList *uris = NULL;
1486 GSList *uri_node = NULL;
1488 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1490 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1491 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1492 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1494 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1496 response = gtk_dialog_run (GTK_DIALOG (dialog));
1498 case GTK_RESPONSE_OK:
1499 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1504 gtk_widget_destroy (dialog);
1506 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1508 GnomeVFSHandle *handle = NULL;
1509 GnomeVFSResult result;
1510 GtkTextIter position;
1511 GtkTextMark *insert_mark;
1513 uri = (const gchar *) uri_node->data;
1514 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1515 if (result == GNOME_VFS_OK) {
1516 GdkPixbufLoader *loader;
1518 GnomeVFSFileInfo info;
1519 gchar *filename, *basename, *escaped_filename;
1520 TnyMimePart *mime_part;
1522 const gchar *mime_type = NULL;
1523 GnomeVFSURI *vfs_uri;
1525 vfs_uri = gnome_vfs_uri_new (uri);
1527 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1528 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1529 g_free (escaped_filename);
1530 gnome_vfs_uri_unref (vfs_uri);
1532 if (gnome_vfs_get_file_info (uri, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
1533 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1535 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1537 mime_part = tny_platform_factory_new_mime_part
1538 (modest_runtime_get_platform_factory ());
1540 TnyStream *stream = create_stream_for_uri (uri);
1541 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1543 content_id = g_strdup_printf ("%d", priv->last_cid);
1544 tny_mime_part_set_content_id (mime_part, content_id);
1545 g_free (content_id);
1548 basename = g_path_get_basename (filename);
1549 tny_mime_part_set_filename (mime_part, basename);
1552 tny_stream_reset (TNY_STREAM (stream));
1553 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1554 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1555 unsigned char read_buffer[128];
1557 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1558 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
1561 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1562 g_object_ref (pixbuf);
1563 gdk_pixbuf_loader_close (loader, NULL);
1564 g_object_unref (loader);
1566 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1567 GdkPixbuf *new_pixbuf;
1569 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1570 gdk_pixbuf_get_width (pixbuf);
1571 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1572 g_object_unref (pixbuf);
1573 pixbuf = new_pixbuf;
1576 if (pixbuf != NULL) {
1577 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1578 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1579 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1582 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1583 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1585 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1586 gtk_widget_show_all (priv->attachments_caption);
1587 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1597 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
1600 ModestMsgEditWindowPrivate *priv;
1601 GtkWidget *dialog = NULL;
1603 GSList *uris = NULL;
1606 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1608 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1609 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
1610 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1612 response = gtk_dialog_run (GTK_DIALOG (dialog));
1614 case GTK_RESPONSE_OK:
1615 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1620 gtk_widget_destroy (dialog);
1622 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1623 const gchar *uri = (const gchar *) uri_node->data;
1624 modest_msg_edit_window_attach_file_one (window, uri);
1626 g_slist_foreach (uris, (GFunc) g_free, NULL);
1627 g_slist_free (uris);
1631 modest_msg_edit_window_attach_file_one (
1632 ModestMsgEditWindow *window,
1635 g_return_if_fail (window);
1636 g_return_if_fail (uri);
1638 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1641 GnomeVFSHandle *handle = NULL;
1642 GnomeVFSResult result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1643 if (result == GNOME_VFS_OK) {
1644 TnyMimePart *mime_part;
1646 const gchar *mime_type = NULL;
1648 gchar *escaped_filename;
1651 GnomeVFSFileInfo info;
1652 GnomeVFSURI *vfs_uri;
1654 vfs_uri = gnome_vfs_uri_new (uri);
1657 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1658 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1659 g_free (escaped_filename);
1660 gnome_vfs_uri_unref (vfs_uri);
1662 if (gnome_vfs_get_file_info (uri,
1664 GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
1665 GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1667 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1668 mime_part = tny_platform_factory_new_mime_part
1669 (modest_runtime_get_platform_factory ());
1670 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1672 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1674 content_id = g_strdup_printf ("%d", priv->last_cid);
1675 tny_mime_part_set_content_id (mime_part, content_id);
1676 g_free (content_id);
1679 basename = g_path_get_basename (filename);
1680 tny_mime_part_set_filename (mime_part, basename);
1683 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1684 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1686 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1687 gtk_widget_show_all (priv->attachments_caption);
1688 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1694 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1697 ModestMsgEditWindowPrivate *priv;
1698 gboolean clean_list = FALSE;
1700 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1701 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1703 if (att_list == NULL) {
1704 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1708 if (att_list == NULL) {
1709 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1711 GtkWidget *confirmation_dialog = NULL;
1712 gboolean dialog_response;
1714 gchar *message = NULL;
1715 const gchar *filename = NULL;
1717 if (att_list->next == NULL) {
1718 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1722 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1723 att_list->next == NULL), filename);
1724 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1726 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1727 gtk_widget_destroy (confirmation_dialog);
1728 if (!dialog_response) {
1730 g_list_free (att_list);
1733 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1735 for (node = att_list; node != NULL; node = g_list_next (node)) {
1736 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1737 const gchar *att_id;
1738 priv->attachments = g_list_remove (priv->attachments, mime_part);
1740 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1742 if (priv->attachments == NULL)
1743 gtk_widget_hide (priv->attachments_caption);
1744 att_id = tny_mime_part_get_content_id (mime_part);
1746 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1748 g_object_unref (mime_part);
1749 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1754 g_list_free (att_list);
1758 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1761 ModestMsgEditWindowPrivate *priv;
1762 GdkColor *new_color;
1763 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1765 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1766 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1769 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1771 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1773 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1775 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1780 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1783 ModestMsgEditWindowPrivate *priv;
1784 gint new_size_index;
1785 ModestMsgEditWindow *window;
1788 window = MODEST_MSG_EDIT_WINDOW (userdata);
1789 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1790 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1792 if (gtk_check_menu_item_get_active (menu_item)) {
1794 WPTextBufferFormat format;
1796 memset (&format, 0, sizeof (format));
1797 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1799 label = gtk_bin_get_child (GTK_BIN (menu_item));
1801 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1802 format.cs.font_size = TRUE;
1803 format.cs.text_position = TRUE;
1804 format.cs.font = TRUE;
1805 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1806 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1808 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1809 (gpointer) wp_get_font_size_index (new_size_index, 12)))
1810 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1812 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1813 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1814 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1820 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1823 ModestMsgEditWindowPrivate *priv;
1824 gint new_font_index;
1825 ModestMsgEditWindow *window;
1828 window = MODEST_MSG_EDIT_WINDOW (userdata);
1829 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1830 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1832 if (gtk_check_menu_item_get_active (menu_item)) {
1835 label = gtk_bin_get_child (GTK_BIN (menu_item));
1837 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1839 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1840 (gpointer) new_font_index))
1841 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1843 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1844 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1845 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1851 modest_msg_edit_window_set_zoom (ModestWindow *window,
1854 ModestMsgEditWindowPrivate *priv;
1855 ModestWindowPrivate *parent_priv;
1856 GtkRadioAction *zoom_radio_action;
1858 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1860 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1861 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1862 priv->zoom_level = zoom;
1863 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom*DEFAULT_FONT_SCALE);
1865 /* Zoom level menu options should be updated with the current zoom level */
1866 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1867 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1868 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1869 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1870 /* FIXME: Not availible before Gtk 2.10 */
1872 gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
1877 modest_msg_edit_window_get_zoom (ModestWindow *window)
1879 ModestMsgEditWindowPrivate *priv;
1881 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1883 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1884 return priv->zoom_level;
1888 zoom_allowed (ModestMsgEditWindow *window)
1892 focus = gtk_window_get_focus (GTK_WINDOW (window));
1893 return (focus != NULL && WP_IS_TEXT_VIEW (focus));
1897 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1899 ModestWindowPrivate *parent_priv;
1900 GtkRadioAction *zoom_radio_action;
1901 GSList *group, *node;
1903 /* First we check if the text view is focused. If not, zooming is not allowed */
1904 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1905 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1909 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1910 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1911 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1913 group = gtk_radio_action_get_group (zoom_radio_action);
1915 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1916 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
1920 for (node = group; node != NULL; node = g_slist_next (node)) {
1921 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1922 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1930 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1932 ModestWindowPrivate *parent_priv;
1933 GtkRadioAction *zoom_radio_action;
1934 GSList *group, *node;
1936 /* First we check if the text view is focused. If not, zooming is not allowed */
1937 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1938 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1942 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1943 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1944 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1946 group = gtk_radio_action_get_group (zoom_radio_action);
1948 for (node = group; node != NULL; node = g_slist_next (node)) {
1949 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1950 if (node->next != NULL) {
1951 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1954 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
1962 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1964 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1965 ModestWindowPrivate *parent_priv;
1966 ModestWindowMgr *mgr;
1967 gboolean is_fullscreen;
1968 GtkAction *fs_toggle_action;
1971 mgr = modest_runtime_get_window_mgr ();
1972 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1974 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1976 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1977 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1978 if (is_fullscreen != active)
1979 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1987 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
1989 ModestWindowPrivate *parent_priv;
1990 GtkAction *fs_toggle_action;
1993 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1995 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1996 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
1997 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
2001 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2004 ModestMsgEditWindowPrivate *priv = NULL;
2005 const gchar *recipients;
2006 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2008 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2009 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2010 recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field));
2011 if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2012 gtk_widget_show (priv->cc_caption);
2014 gtk_widget_hide (priv->cc_caption);
2015 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2019 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2022 ModestMsgEditWindowPrivate *priv = NULL;
2023 const gchar *recipients;
2024 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2026 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2027 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2028 recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field));
2029 if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2030 gtk_widget_show (priv->bcc_caption);
2032 gtk_widget_hide (priv->bcc_caption);
2033 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2037 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2038 ModestRecptEditor *editor)
2040 ModestMsgEditWindowPrivate *priv;
2042 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2043 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2044 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2046 if (editor == NULL) {
2047 GtkWidget *view_focus;
2048 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2050 /* This code should be kept in sync with ModestRecptEditor. The
2051 textview inside the recpt editor is the one that really gets the
2052 focus. As it's inside a scrolled window, and this one inside the
2053 hbox recpt editor inherits from, we'll need to go up in the
2054 hierarchy to know if the text view is part of the recpt editor
2055 or if it's a different text entry */
2057 if (gtk_widget_get_parent (view_focus)) {
2058 GtkWidget *first_parent;
2060 first_parent = gtk_widget_get_parent (view_focus);
2061 if (gtk_widget_get_parent (first_parent) &&
2062 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2063 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2068 editor = MODEST_RECPT_EDITOR (priv->to_field);
2072 modest_address_book_select_addresses (editor);
2077 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2079 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2081 modest_msg_edit_window_open_addressbook (window, NULL);
2085 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2086 gboolean show_toolbar)
2088 ModestWindowPrivate *parent_priv;
2090 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2091 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2093 /* FIXME: we can not just use the code of
2094 modest_msg_edit_window_setup_toolbar because it has a
2095 mixture of both initialization and creation code. */
2098 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2100 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2104 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2105 TnyHeaderFlags priority_flags)
2107 ModestMsgEditWindowPrivate *priv;
2108 ModestWindowPrivate *parent_priv;
2110 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2112 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2113 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2114 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2116 if (priv->priority_flags != priority_flags) {
2117 GtkAction *priority_action = NULL;
2119 priv->priority_flags = priority_flags;
2121 switch (priority_flags) {
2122 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2123 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2124 gtk_widget_show (priv->priority_icon);
2125 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2126 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2128 case TNY_HEADER_FLAG_LOW_PRIORITY:
2129 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2130 gtk_widget_show (priv->priority_icon);
2131 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2132 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2135 gtk_widget_hide (priv->priority_icon);
2136 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2137 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2140 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2141 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2146 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2149 ModestMsgEditWindowPrivate *priv;
2150 ModestWindowPrivate *parent_priv;
2151 gint current_format;
2153 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2155 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2156 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2158 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2159 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2161 if (current_format != file_format) {
2162 switch (file_format) {
2163 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2164 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2166 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2170 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2171 response = gtk_dialog_run (GTK_DIALOG (dialog));
2172 gtk_widget_destroy (dialog);
2173 if (response == GTK_RESPONSE_OK) {
2174 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2176 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2177 toggle_action_set_active_block_notify (action, TRUE);
2182 update_dimmed (window);
2187 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2190 ModestMsgEditWindowPrivate *priv;
2191 WPTextBufferFormat oldfmt, fmt;
2192 gint old_position = 0;
2196 GdkColor *color = NULL;
2197 gboolean bold, bold_set, italic, italic_set;
2198 gboolean underline, underline_set;
2199 gboolean strikethrough, strikethrough_set;
2200 gboolean position_set;
2201 gboolean font_size_set, font_set, color_set;
2204 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2205 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2207 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2209 /* First we get the currently selected font information */
2210 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2211 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2213 switch (oldfmt.text_position) {
2214 case TEXT_POSITION_NORMAL:
2217 case TEXT_POSITION_SUPERSCRIPT:
2225 g_object_set (G_OBJECT (dialog),
2226 "bold", oldfmt.bold != FALSE,
2227 "bold-set", !oldfmt.cs.bold,
2228 "underline", oldfmt.underline != FALSE,
2229 "underline-set", !oldfmt.cs.underline,
2230 "italic", oldfmt.italic != FALSE,
2231 "italic-set", !oldfmt.cs.italic,
2232 "strikethrough", oldfmt.strikethrough != FALSE,
2233 "strikethrough-set", !oldfmt.cs.strikethrough,
2234 "color", &oldfmt.color,
2235 "color-set", !oldfmt.cs.color,
2236 "size", wp_font_size[oldfmt.font_size],
2237 "size-set", !oldfmt.cs.font_size,
2238 "position", old_position,
2239 "position-set", !oldfmt.cs.text_position,
2240 "family", wp_get_font_name (oldfmt.font),
2241 "family-set", !oldfmt.cs.font,
2244 gtk_widget_show_all (dialog);
2245 response = gtk_dialog_run (GTK_DIALOG (dialog));
2246 if (response == GTK_RESPONSE_OK) {
2248 g_object_get( dialog,
2250 "bold-set", &bold_set,
2251 "underline", &underline,
2252 "underline-set", &underline_set,
2254 "italic-set", &italic_set,
2255 "strikethrough", &strikethrough,
2256 "strikethrough-set", &strikethrough_set,
2258 "color-set", &color_set,
2260 "size-set", &font_size_set,
2261 "family", &font_name,
2262 "family-set", &font_set,
2263 "position", &position,
2264 "position-set", &position_set,
2269 if (response == GTK_RESPONSE_OK) {
2270 memset(&fmt, 0, sizeof(fmt));
2276 fmt.italic = italic;
2277 fmt.cs.italic = TRUE;
2279 if (underline_set) {
2280 fmt.underline = underline;
2281 fmt.cs.underline = TRUE;
2283 if (strikethrough_set) {
2284 fmt.strikethrough = strikethrough;
2285 fmt.cs.strikethrough = TRUE;
2290 ? TEXT_POSITION_NORMAL
2291 : ( ( position == 1 )
2292 ? TEXT_POSITION_SUPERSCRIPT
2293 : TEXT_POSITION_SUBSCRIPT );
2294 fmt.cs.text_position = TRUE;
2298 fmt.cs.color = TRUE;
2301 fmt.font = wp_get_font_index(font_name,
2306 if (font_size_set) {
2307 fmt.font_size = wp_get_font_size_index(
2308 font_size, DEFAULT_FONT_SIZE);
2309 fmt.cs.font_size = TRUE;
2311 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2313 gtk_widget_destroy (dialog);
2315 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2319 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2321 ModestMsgEditWindowPrivate *priv;
2323 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2324 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2326 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2328 update_dimmed (window);
2333 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2335 ModestMsgEditWindowPrivate *priv;
2337 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2338 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2340 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2342 update_dimmed (window);
2347 update_dimmed (ModestMsgEditWindow *window)
2349 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2350 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2354 gboolean editor_focused;
2356 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2357 editor_focused = gtk_widget_is_focus (priv->msg_body);
2359 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2360 gtk_action_set_sensitive (action, rich_text && editor_focused);
2361 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2362 gtk_action_set_sensitive (action, rich_text && editor_focused);
2363 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2364 gtk_action_set_sensitive (action, rich_text && editor_focused);
2365 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2366 gtk_action_set_sensitive (action, rich_text && editor_focused);
2367 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2368 gtk_action_set_sensitive (action, rich_text && editor_focused);
2369 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2370 gtk_action_set_sensitive (action, rich_text && editor_focused);
2371 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2372 gtk_action_set_sensitive (action, rich_text && editor_focused);
2373 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2374 gtk_action_set_sensitive (action, rich_text && editor_focused);
2375 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2376 gtk_action_set_sensitive (action, rich_text && editor_focused);
2377 widget = priv->font_color_button;
2378 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2379 widget = priv->font_size_toolitem;
2380 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2381 widget = priv->font_face_toolitem;
2382 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2386 setup_insensitive_handlers (ModestMsgEditWindow *window)
2388 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2389 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2392 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2393 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2394 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2395 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2396 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2397 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2398 widget = priv->font_color_button;
2399 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2400 widget = priv->font_size_toolitem;
2401 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2402 widget = priv->font_face_toolitem;
2403 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2408 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2410 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2413 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2414 gtk_action_set_sensitive (action, can_undo);
2418 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2420 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2423 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/RedoMenu");
2424 gtk_action_set_sensitive (action, can_redo);
2428 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2431 GtkTextIter match_start, match_end;
2433 if (image_id == NULL)
2436 gtk_text_buffer_get_start_iter (buffer, &iter);
2438 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2439 GSList *tags = gtk_text_iter_get_tags (&match_start);
2441 for (node = tags; node != NULL; node = g_slist_next (node)) {
2442 GtkTextTag *tag = (GtkTextTag *) node->data;
2443 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2444 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2445 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2447 offset = gtk_text_iter_get_offset (&match_start);
2448 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2449 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2453 gtk_text_iter_forward_char (&iter);
2458 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2460 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2461 GtkTextIter real_start, real_end;
2462 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2464 if (gtk_text_iter_compare (start, end) > 0) {
2468 real_start = *start;
2472 GSList *tags = gtk_text_iter_get_tags (&real_start);
2474 for (node = tags; node != NULL; node = g_slist_next (node)) {
2475 GtkTextTag *tag = (GtkTextTag *) node->data;
2476 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2477 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2479 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2481 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2484 } while (gtk_text_iter_forward_char (&real_start)&&
2485 (gtk_text_iter_compare (&real_start, &real_end)<=0));
2489 msg_body_focus (GtkWidget *focus,
2490 GdkEventFocus *event,
2494 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2499 recpt_field_changed (GtkTextBuffer *buffer,
2500 ModestMsgEditWindow *editor)
2502 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2503 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2504 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2505 gboolean dim = FALSE;
2508 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2509 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2510 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2512 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2513 gtk_text_buffer_get_char_count (cc_buffer) +
2514 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2516 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2517 gtk_action_set_sensitive (action, !dim);
2518 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2519 gtk_action_set_sensitive (action, !dim);
2523 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2525 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2529 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2531 gboolean rich_text, editor_focused;
2533 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2534 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2535 editor_focused = gtk_widget_is_focus (priv->msg_body);
2538 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2539 else if (!editor_focused)
2540 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2544 reset_modified (ModestMsgEditWindow *editor)
2546 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2547 GtkTextBuffer *buffer;
2549 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2550 gtk_text_buffer_set_modified (buffer, FALSE);
2551 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2552 gtk_text_buffer_set_modified (buffer, FALSE);
2553 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2554 gtk_text_buffer_set_modified (buffer, FALSE);
2555 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2559 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2561 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2562 GtkTextBuffer *buffer;
2564 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2565 if (gtk_text_buffer_get_modified (buffer))
2567 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2568 if (gtk_text_buffer_get_modified (buffer))
2570 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2571 if (gtk_text_buffer_get_modified (buffer))
2573 if (gtk_text_buffer_get_modified (priv->text_buffer))
2580 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
2582 ModestMsgEditWindowPrivate *priv = NULL;
2584 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2585 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2587 /* check if there's no recipient added */
2588 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2589 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2590 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2591 /* no recipient contents, then select contacts */
2592 modest_msg_edit_window_open_addressbook (window, NULL);
2596 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook))
2598 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook))
2600 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook))
2603 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2610 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2611 ModestMsgEditWindow *window)
2613 modest_msg_edit_window_offer_attach_file (window);
2617 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2619 ModestMsgEditWindow *window)
2621 ModestWindowPrivate *parent_priv;
2622 ModestMsgEditWindowPrivate *priv;
2624 gboolean has_selection;
2626 GList *selected_attachments = NULL;
2627 gint n_att_selected = 0;
2629 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2630 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2632 if (!GTK_WIDGET_VISIBLE (window))
2634 has_selection = gtk_clipboard_wait_for_targets (clipboard, NULL, NULL);
2635 focused = gtk_window_get_focus (GTK_WINDOW (window));
2637 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2638 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2639 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2640 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2642 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2643 n_att_selected = g_list_length (selected_attachments);
2644 g_list_free (selected_attachments);
2646 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2647 gtk_action_set_sensitive (action, n_att_selected == 1);
2649 update_paste_dimming (window);
2653 update_window_title (ModestMsgEditWindow *window)
2655 ModestMsgEditWindowPrivate *priv = NULL;
2656 const gchar *subject;
2658 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2659 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2660 if (subject == NULL || subject[0] == '\0')
2661 subject = _("mail_va_new_email");
2663 gtk_window_set_title (GTK_WINDOW (window), subject);
2668 subject_field_changed (GtkEditable *editable,
2669 ModestMsgEditWindow *window)
2671 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2672 update_window_title (window);
2673 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2677 message_is_empty (ModestMsgEditWindow *window)
2679 ModestMsgEditWindowPrivate *priv = NULL;
2681 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2682 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2684 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
2685 * so we can ignore markup.
2687 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
2690 count = gtk_text_buffer_get_char_count (buf);
2696 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2699 ModestMsgEditWindowPrivate *priv = NULL;
2701 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2702 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2704 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2706 /* Show a warning if there is nothing to search: */
2707 if (show && message_is_empty (window)) {
2708 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
2713 gtk_widget_show_all (priv->find_toolbar);
2714 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2716 gtk_widget_hide_all (priv->find_toolbar);
2717 gtk_widget_grab_focus (priv->msg_body);
2723 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2725 GtkTextIter *match_start,
2726 GtkTextIter *match_end)
2728 GtkTextIter end_iter;
2729 gchar *str_casefold;
2732 gchar *range_casefold;
2735 gboolean result = FALSE;
2742 gtk_text_iter_forward_to_end (&end_iter);
2744 str_casefold = g_utf8_casefold (str, -1);
2745 str_chars_n = strlen (str);
2747 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2748 range_casefold = g_utf8_casefold (range_text, -1);
2749 range_chars_n = strlen (range_casefold);
2751 if (range_chars_n < str_chars_n) {
2752 g_free (str_casefold);
2753 g_free (range_text);
2754 g_free (range_casefold);
2758 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2759 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2760 if (!g_utf8_collate (range_subtext, str_casefold)) {
2761 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2763 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2764 match_start, match_end, NULL);
2765 g_free (found_text);
2767 g_free (range_subtext);
2771 g_free (str_casefold);
2772 g_free (range_text);
2773 g_free (range_casefold);
2780 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2781 ModestMsgEditWindow *window)
2783 gchar *current_search = NULL;
2784 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2786 GtkTextIter selection_start, selection_end;
2787 GtkTextIter match_start, match_end;
2788 gboolean continue_search = FALSE;
2790 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2791 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2792 g_free (current_search);
2793 g_free (priv->last_search);
2794 priv->last_search = NULL;
2795 /* Information banner about empty search */
2796 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2800 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2801 continue_search = TRUE;
2803 g_free (priv->last_search);
2804 priv->last_search = g_strdup (current_search);
2807 if (continue_search) {
2808 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2809 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2810 &match_start, &match_end);
2812 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2814 GtkTextIter buffer_start;
2815 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2816 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2817 &match_start, &match_end);
2819 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2822 /* Mark as selected the string found in search */
2824 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2825 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2827 g_free (priv->last_search);
2828 priv->last_search = NULL;
2830 g_free (current_search);
2834 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2835 ModestMsgEditWindow *window)
2837 GtkToggleAction *toggle;
2838 ModestWindowPrivate *parent_priv;
2839 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2841 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2842 gtk_toggle_action_set_active (toggle, FALSE);
2847 update_paste_dimming (ModestMsgEditWindow *window)
2849 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2850 GtkAction *action = NULL;
2851 GtkClipboard *clipboard = NULL;
2855 focused = gtk_window_get_focus (GTK_WINDOW (window));
2857 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2858 active = gtk_clipboard_wait_is_text_available (clipboard);
2861 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2865 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2866 gtk_action_set_sensitive (action, active);
2871 update_select_all_dimming (ModestMsgEditWindow *window)
2874 gboolean dimmed = FALSE;
2876 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2878 focused = gtk_window_get_focus (GTK_WINDOW (window));
2879 if (GTK_IS_ENTRY (focused)) {
2880 const gchar *current_text;
2881 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
2882 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
2883 } else if (GTK_IS_TEXT_VIEW (focused)) {
2884 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
2885 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
2886 } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
2889 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
2890 gtk_action_set_sensitive (action, !dimmed);
2894 update_zoom_dimming (ModestMsgEditWindow *window)
2897 gboolean dimmed = FALSE;
2899 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2901 focused = gtk_window_get_focus (GTK_WINDOW (window));
2902 dimmed = ! WP_IS_TEXT_VIEW (focused);
2903 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2904 gtk_action_set_sensitive (action, !dimmed);
2908 edit_menu_activated (GtkAction *action,
2911 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2913 update_select_all_dimming (window);
2914 update_paste_dimming (window);
2917 view_menu_activated (GtkAction *action,
2920 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2922 update_zoom_dimming (window);
2926 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
2928 ModestMsgEditWindowPrivate *priv;
2930 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
2935 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
2938 ModestMsgEditWindowPrivate *priv;
2940 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
2946 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
2949 ModestMsgEditWindowPrivate *priv;
2950 TnyHeader *header = NULL;
2952 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2953 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
2955 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2956 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
2958 if (priv->draft_msg != NULL) {
2959 header = tny_msg_get_header (priv->draft_msg);
2960 if (TNY_IS_HEADER (header)) {
2961 modest_window_mgr_unregister_header (mgr, header);
2963 g_object_unref (priv->draft_msg);
2966 if (draft != NULL) {
2967 g_object_ref (draft);
2968 header = tny_msg_get_header (draft);
2969 if (TNY_IS_HEADER (header))
2970 modest_window_mgr_register_header (mgr, header);
2973 priv->draft_msg = draft;