1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
41 #include <modest-account-mgr.h>
42 #include <modest-account-mgr-helpers.h>
44 #include <widgets/modest-msg-edit-window.h>
45 #include <widgets/modest-combo-box.h>
46 #include <widgets/modest-recpt-editor.h>
47 #include <widgets/modest-attachments-view.h>
49 #include <modest-runtime.h>
51 #include "modest-platform.h"
52 #include "modest-icon-names.h"
53 #include "modest-widget-memory.h"
54 #include "modest-window-priv.h"
55 #include "modest-mail-operation.h"
56 #include "modest-tny-platform-factory.h"
57 #include "modest-tny-msg.h"
58 #include "modest-tny-folder.h"
59 #include "modest-address-book.h"
60 #include "modest-text-utils.h"
61 #include <tny-simple-list.h>
62 #include <wptextview.h>
63 #include <wptextbuffer.h>
64 #include "modest-scroll-area.h"
66 #include "modest-hildon-includes.h"
67 #ifdef MODEST_HAVE_HILDON0_WIDGETS
68 #include <hildon-widgets/hildon-color-chooser.h>
70 #include "widgets/modest-msg-edit-window-ui.h"
71 #ifdef MODEST_HAVE_HILDON0_WIDGETS
72 #include <libgnomevfs/gnome-vfs-mime-utils.h>
74 #include <libgnomevfs/gnome-vfs-mime.h>
76 #include "modest-maemo-utils.h"
79 #define DEFAULT_FONT_SIZE 3
80 #define DEFAULT_FONT 2
81 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
82 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
83 #define DEFAULT_MAIN_VBOX_SPACING 6
84 #define SUBJECT_MAX_LENGTH 1000
85 #define IMAGE_MAX_WIDTH 608
86 #define DEFAULT_FONT_SCALE 1.5
88 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
89 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
90 static void modest_msg_edit_window_finalize (GObject *obj);
92 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
93 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
94 static void send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
95 static void style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
96 static void setup_insensitive_handlers (ModestMsgEditWindow *editor);
97 static void reset_modified (ModestMsgEditWindow *editor);
99 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
100 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
101 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
102 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
103 GtkTextIter *start, GtkTextIter *end,
105 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
106 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
107 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
109 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
111 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
113 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
114 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
115 GdkEventWindowState *event,
117 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
118 ModestRecptEditor *editor);
119 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
120 ModestMsgEditWindow *window);
122 /* ModestWindow methods implementation */
123 static void modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom);
124 static gdouble modest_msg_edit_window_get_zoom (ModestWindow *window);
125 static gboolean modest_msg_edit_window_zoom_minus (ModestWindow *window);
126 static gboolean modest_msg_edit_window_zoom_plus (ModestWindow *window);
127 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
128 gboolean show_toolbar);
129 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
131 ModestMsgEditWindow *window);
132 static void update_window_title (ModestMsgEditWindow *window);
133 static void update_dimmed (ModestMsgEditWindow *window);
134 static void update_paste_dimming (ModestMsgEditWindow *window);
135 static void update_select_all_dimming (ModestMsgEditWindow *window);
136 static void update_zoom_dimming (ModestMsgEditWindow *window);
139 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
140 ModestMsgEditWindow *window);
141 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
142 ModestMsgEditWindow *window);
143 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
145 GtkTextIter *match_start,
146 GtkTextIter *match_end);
148 static void DEBUG_BUFFER (WPTextBuffer *buffer)
153 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
154 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
155 while (!gtk_text_iter_is_end (&iter)) {
156 GString *output = g_string_new ("");
157 GSList *toggled_tags;
160 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
161 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
162 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
163 GtkTextTag *tag = (GtkTextTag *) node->data;
165 g_object_get (G_OBJECT (tag), "name", &name, NULL);
166 output = g_string_append (output, name);
167 g_string_append (output, " ");
169 output = g_string_append (output, "] OPENED [ ");
170 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
171 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
172 GtkTextTag *tag = (GtkTextTag *) node->data;
174 g_object_get (G_OBJECT (tag), "name", &name, NULL);
175 output = g_string_append (output, name);
176 g_string_append (output, " ");
178 output = g_string_append (output, "]\n");
179 g_message ("%s", output->str);
180 g_string_free (output, TRUE);
181 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
183 g_message ("END BUFFER");
188 /* static gboolean */
189 /* on_key_pressed (GtkWidget *self, */
190 /* GdkEventKey *event, */
191 /* gpointer user_data); */
193 static void edit_menu_activated (GtkAction *action,
195 static void view_menu_activated (GtkAction *action,
198 /* list my signals */
205 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
206 struct _ModestMsgEditWindowPrivate {
208 GtkWidget *header_box;
210 ModestPairList *from_field_protos;
211 GtkWidget *from_field;
215 GtkWidget *bcc_field;
216 GtkWidget *subject_field;
217 GtkWidget *attachments_view;
218 GtkWidget *priority_icon;
219 GtkWidget *add_attachment_button;
221 GtkWidget *cc_caption;
222 GtkWidget *bcc_caption;
223 gboolean update_caption_visibility;
224 GtkWidget *attachments_caption;
226 GtkTextBuffer *text_buffer;
228 GtkWidget *font_size_toolitem;
229 GtkWidget *font_face_toolitem;
230 GtkWidget *font_color_button;
231 GSList *font_items_group;
232 GtkWidget *font_tool_button_label;
233 GSList *size_items_group;
234 GtkWidget *size_tool_button_label;
236 GtkWidget *find_toolbar;
240 GtkWidget *scroll_area;
245 TnyHeaderFlags priority_flags;
249 gulong clipboard_change_handler_id;
255 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
256 MODEST_TYPE_MSG_EDIT_WINDOW, \
257 ModestMsgEditWindowPrivate))
259 static GtkWindowClass *parent_class = NULL;
261 /* uncomment the following if you have defined any signals */
262 /* static guint signals[LAST_SIGNAL] = {0}; */
265 modest_msg_edit_window_get_type (void)
267 static GType my_type = 0;
269 static const GTypeInfo my_info = {
270 sizeof(ModestMsgEditWindowClass),
271 NULL, /* base init */
272 NULL, /* base finalize */
273 (GClassInitFunc) modest_msg_edit_window_class_init,
274 NULL, /* class finalize */
275 NULL, /* class data */
276 sizeof(ModestMsgEditWindow),
278 (GInstanceInitFunc) modest_msg_edit_window_init,
281 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
282 "ModestMsgEditWindow",
285 wp_text_buffer_library_init ();
291 save_state (ModestWindow *self)
293 modest_widget_memory_save (modest_runtime_get_conf(),
294 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
299 restore_settings (ModestMsgEditWindow *self)
301 modest_widget_memory_restore (modest_runtime_get_conf(),
302 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
307 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
309 GObjectClass *gobject_class;
310 ModestWindowClass *modest_window_class;
311 gobject_class = (GObjectClass*) klass;
312 modest_window_class = (ModestWindowClass*) klass;
314 parent_class = g_type_class_peek_parent (klass);
315 gobject_class->finalize = modest_msg_edit_window_finalize;
317 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
318 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
319 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
320 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
321 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
322 modest_window_class->save_state_func = save_state;
324 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
330 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
332 ModestMsgEditWindowPrivate *priv;
333 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
335 priv->msg_body = NULL;
336 priv->from_field = NULL;
337 priv->to_field = NULL;
338 priv->cc_field = NULL;
339 priv->bcc_field = NULL;
340 priv->subject_field = NULL;
341 priv->attachments = NULL;
343 priv->zoom_level = 1.0;
345 priv->cc_caption = NULL;
346 priv->bcc_caption = NULL;
347 priv->update_caption_visibility = FALSE;
349 priv->priority_flags = 0;
351 priv->find_toolbar = NULL;
352 priv->last_search = NULL;
354 priv->draft_msg = NULL;
355 priv->clipboard_change_handler_id = 0;
360 /* FIXME: this is a dup from the one in gtk/ */
363 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
365 static ModestPairList*
366 get_transports (void)
368 GSList *transports = NULL;
370 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
371 GSList *accounts = modest_account_mgr_account_names (account_mgr,
372 TRUE /* only enabled accounts. */);
374 GSList *cursor = accounts;
376 gchar *account_name = cursor->data;
377 gchar *from_string = NULL;
379 from_string = modest_account_mgr_get_from_string (account_mgr,
383 if (from_string && account_name) {
384 gchar *name = account_name;
385 ModestPair *pair = modest_pair_new ((gpointer) name,
386 (gpointer) from_string , TRUE);
387 transports = g_slist_prepend (transports, pair);
390 cursor = cursor->next;
392 g_slist_free (accounts); /* only free the accounts, not the elements,
393 * because they are used in the pairlist */
399 init_window (ModestMsgEditWindow *obj)
401 GtkWidget *from_caption, *to_caption, *subject_caption;
402 GtkWidget *main_vbox;
403 ModestMsgEditWindowPrivate *priv;
405 GtkSizeGroup *size_group;
407 GtkWidget *subject_box;
408 GtkWidget *attachment_icon;
409 GtkWidget *window_box;
410 #if (GTK_MINOR_VERSION >= 10)
411 GdkAtom deserialize_type;
413 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
415 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
417 /* Note: This ModestPairList* must exist for as long as the combo
418 * that uses it, because the ModestComboBox uses the ID opaquely,
419 * so it can't know how to manage its memory. */
420 priv->from_field_protos = get_transports ();
422 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
424 priv->to_field = modest_recpt_editor_new ();
425 priv->cc_field = modest_recpt_editor_new ();
426 priv->bcc_field = modest_recpt_editor_new ();
427 subject_box = gtk_hbox_new (FALSE, 0);
428 priv->priority_icon = gtk_image_new ();
429 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
430 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
431 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
432 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
433 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
434 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
435 priv->add_attachment_button = gtk_button_new ();
436 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
437 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
438 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
439 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
440 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
441 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
442 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
443 priv->attachments_view = modest_attachments_view_new (NULL);
445 priv->header_box = gtk_vbox_new (FALSE, 0);
447 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
448 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
449 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
450 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
451 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
452 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
453 g_object_unref (size_group);
455 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
456 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
457 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
458 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
459 gtk_size_group_add_widget (size_group, priv->subject_field);
460 gtk_size_group_add_widget (size_group, priv->attachments_view);
461 g_object_unref (size_group);
463 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
464 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
465 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
466 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
467 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
468 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
469 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
472 priv->msg_body = wp_text_view_new ();
473 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
474 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
475 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
476 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
477 #if (GTK_MINOR_VERSION >= 10)
478 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
479 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
481 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
482 deserialize_type, TRUE);
484 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
486 priv->find_toolbar = hildon_find_toolbar_new (NULL);
487 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
489 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
491 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
492 G_CALLBACK (text_buffer_refresh_attributes), obj);
493 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
494 G_CALLBACK (text_buffer_can_undo), obj);
495 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
496 G_CALLBACK (text_buffer_can_redo), obj);
497 g_signal_connect (G_OBJECT (obj), "window-state-event",
498 G_CALLBACK (modest_msg_edit_window_window_state_event),
500 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
501 G_CALLBACK (text_buffer_apply_tag), obj);
502 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
503 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
504 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
505 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
506 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
507 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
509 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
510 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
512 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
513 G_CALLBACK (msg_body_focus), obj);
514 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
515 G_CALLBACK (msg_body_focus), obj);
516 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
517 "changed", G_CALLBACK (recpt_field_changed), obj);
518 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
519 "changed", G_CALLBACK (recpt_field_changed), obj);
520 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
521 "changed", G_CALLBACK (recpt_field_changed), obj);
522 recpt_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
523 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
525 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
526 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
528 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
529 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
530 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
531 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
533 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
535 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
536 frame = gtk_frame_new (NULL);
537 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
539 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
540 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
541 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
543 window_box = gtk_vbox_new (FALSE, 0);
544 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
545 gtk_container_add (GTK_CONTAINER(obj), window_box);
546 priv->scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
547 gtk_container_add (GTK_CONTAINER (frame), priv->scroll_area);
549 gtk_container_set_focus_vadjustment (GTK_CONTAINER (priv->scroll_area),
550 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
552 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
553 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
560 modest_msg_edit_window_finalize (GObject *obj)
562 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
564 if (priv->clipboard_change_handler_id > 0) {
565 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), priv->clipboard_change_handler_id);
566 priv->clipboard_change_handler_id = 0;
569 if (priv->draft_msg != NULL) {
570 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
571 if (TNY_IS_HEADER (header)) {
572 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
573 modest_window_mgr_unregister_header (mgr, header);
575 g_object_unref (priv->draft_msg);
576 priv->draft_msg = NULL;
579 /* This had to stay alive for as long as the combobox that used it: */
580 modest_pair_list_free (priv->from_field_protos);
582 G_OBJECT_CLASS(parent_class)->finalize (obj);
586 menubar_to_menu (GtkUIManager *ui_manager)
588 GtkWidget *main_menu;
592 /* Create new main menu */
593 main_menu = gtk_menu_new();
595 /* Get the menubar from the UI manager */
596 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
598 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
602 menu = GTK_WIDGET (iter->data);
603 gtk_widget_reparent(menu, main_menu);
605 iter = g_list_next (iter);
611 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type)
613 GdkPixbufLoader *loader;
616 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
621 tny_stream_reset (TNY_STREAM (stream));
622 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
623 unsigned char read_buffer[128];
625 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
626 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
630 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
631 g_object_ref (pixbuf);
632 gdk_pixbuf_loader_close (loader, NULL);
633 g_object_unref (loader);
635 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
636 GdkPixbuf *new_pixbuf;
638 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
639 gdk_pixbuf_get_width (pixbuf);
640 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
641 g_object_unref (pixbuf);
649 replace_with_attachments (ModestMsgEditWindow *self, GList *attachments)
651 ModestMsgEditWindowPrivate *priv;
654 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
656 for (node = attachments; node != NULL; node = g_list_next (node)) {
657 TnyMimePart *part = (TnyMimePart *) node->data;
658 const gchar *cid = tny_mime_part_get_content_id (part);
659 const gchar *mime_type = tny_mime_part_get_content_type (part);
660 if ((cid != NULL)&&(mime_type != NULL)) {
661 TnyStream *stream = tny_mime_part_get_stream (part);
662 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type);
663 g_object_unref (stream);
665 if (pixbuf != NULL) {
666 /* TODO: Use this when this function is available: */
667 /* wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf); */
668 g_object_unref (pixbuf);
675 update_last_cid (ModestMsgEditWindow *self, GList *attachments)
678 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
680 for (node = attachments; node != NULL; node = g_list_next (node)) {
681 TnyMimePart *part = (TnyMimePart *) node->data;
682 const gchar *cid = tny_mime_part_get_content_id (part);
684 char *invalid = NULL;
685 gint int_cid = strtol (cid, &invalid, 10);
686 if ((invalid != NULL) && (*invalid == '\0') && (int_cid > priv->last_cid)) {
687 priv->last_cid = int_cid;
695 set_msg (ModestMsgEditWindow *self, TnyMsg *msg)
698 const gchar *to, *cc, *bcc, *subject;
700 ModestMsgEditWindowPrivate *priv;
702 TnyHeaderFlags priority_flags;
703 TnyFolder *msg_folder;
705 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
706 g_return_if_fail (TNY_IS_MSG (msg));
708 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
710 header = tny_msg_get_header (msg);
711 to = tny_header_get_to (header);
712 cc = tny_header_get_cc (header);
713 bcc = tny_header_get_bcc (header);
714 subject = tny_header_get_subject (header);
715 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
718 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
720 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
721 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
722 gtk_widget_show (priv->cc_caption);
723 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
724 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
725 gtk_widget_hide (priv->cc_caption);
728 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
729 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
730 gtk_widget_show (priv->bcc_caption);
731 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
732 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
733 gtk_widget_hide (priv->bcc_caption);
736 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
737 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
740 update_window_title (self);
742 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
743 body = modest_tny_msg_get_body (msg, TRUE);
745 if ((body == NULL)||(body[0] == '\0')) {
747 body = modest_text_utils_convert_to_html ("");
749 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
750 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
753 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
756 /* Get the default format required from configuration */
757 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
758 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
761 /* Set the default focus depending on having already a To: field or not */
762 if ((!to)||(*to == '\0')) {
763 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
765 gtk_widget_grab_focus (priv->msg_body);
768 /* TODO: lower priority, select in the From: combo to the
769 value that comes from msg <- not sure, should it be
772 /* Add attachments to the view */
773 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
774 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
775 if (priv->attachments == NULL) {
776 gtk_widget_hide (priv->attachments_caption);
778 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
779 gtk_widget_show_all (priv->attachments_caption);
780 replace_with_attachments (self, priv->attachments);
782 update_last_cid (self, priv->attachments);
784 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
786 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
787 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
789 reset_modified (self);
791 update_dimmed (self);
792 text_buffer_can_undo (priv->text_buffer, FALSE, self);
793 text_buffer_can_redo (priv->text_buffer, FALSE, self);
795 /* we should set a reference to the incoming message if it is a draft */
796 msg_folder = tny_msg_get_folder (msg);
798 if (modest_tny_folder_is_local_folder (msg_folder) &&
799 modest_tny_folder_get_local_or_mmc_folder_type (msg_folder) == TNY_FOLDER_TYPE_DRAFTS)
800 priv->draft_msg = g_object_ref(msg);
801 g_object_unref (msg_folder);
806 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
809 GList *item_children, *node;
810 GtkWidget *bin_child;
812 bin_child = gtk_bin_get_child (GTK_BIN(item));
814 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
816 for (node = item_children; node != NULL; node = g_list_next (node)) {
817 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
818 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
821 g_list_free (item_children);
825 menu_tool_button_dont_expand (GtkMenuToolButton *item)
828 GList *item_children, *node;
830 box = gtk_bin_get_child (GTK_BIN (item));
831 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
832 item_children = gtk_container_get_children (GTK_CONTAINER (box));
834 for (node = item_children; node != NULL; node = g_list_next (node)) {
835 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
836 if (GTK_IS_TOGGLE_BUTTON (node->data))
837 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
838 else if (GTK_IS_BUTTON (node->data))
839 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
841 g_list_free (item_children);
846 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
848 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
849 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
850 GtkWidget *placeholder;
851 GtkWidget *tool_item;
856 GtkWidget *sizes_menu;
857 GtkWidget *fonts_menu;
858 GSList *radio_group = NULL;
863 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
864 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
866 /* should we hide the toolbar? */
867 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
868 gtk_widget_hide (parent_priv->toolbar);
870 /* Font color placeholder */
871 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
872 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
875 tool_item = GTK_WIDGET (gtk_tool_item_new ());
876 priv->font_color_button = hildon_color_button_new ();
877 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
878 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
879 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
880 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
881 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
882 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
883 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
885 /* Font size and face placeholder */
886 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
887 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
889 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
890 priv->size_tool_button_label = gtk_label_new (NULL);
891 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
892 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
893 size_text,"</span>", NULL);
894 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
896 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
897 sizes_menu = gtk_menu_new ();
898 priv->size_items_group = NULL;
900 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
901 GtkWidget *size_menu_item;
903 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
904 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
905 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
906 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
907 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
908 gtk_widget_show (size_menu_item);
910 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
914 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
915 GtkWidget *item = (GtkWidget *) node->data;
916 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
920 priv->size_items_group = g_slist_reverse (priv->size_items_group);
921 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
922 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
923 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
924 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
925 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
926 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
927 priv->font_size_toolitem = tool_item;
930 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
931 priv->font_tool_button_label = gtk_label_new (NULL);
932 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
933 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
935 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
936 fonts_menu = gtk_menu_new ();
937 priv->font_items_group = NULL;
939 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
940 GtkWidget *font_menu_item;
941 GtkWidget *child_label;
943 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
944 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
945 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
946 wp_get_font_name (font_index), "</span>", NULL);
947 gtk_label_set_markup (GTK_LABEL (child_label), markup);
950 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
951 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
952 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
953 gtk_widget_show (font_menu_item);
955 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
958 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
959 GtkWidget *item = (GtkWidget *) node->data;
960 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
963 priv->font_items_group = g_slist_reverse (priv->font_items_group);
964 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
965 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
966 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
967 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
968 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
969 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
970 priv->font_face_toolitem = tool_item;
972 /* Set expand and homogeneous for remaining items */
973 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
974 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
975 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
976 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
977 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
978 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
979 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
980 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
981 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
989 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name)
992 ModestWindowPrivate *parent_priv;
993 ModestMsgEditWindowPrivate *priv;
994 GtkActionGroup *action_group;
995 GError *error = NULL;
996 GdkPixbuf *window_icon = NULL;
999 gboolean prefer_formatted;
1001 ModestPair *account_pair = NULL;
1003 g_return_val_if_fail (msg, NULL);
1004 g_return_val_if_fail (account_name, NULL);
1006 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
1008 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1009 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1011 parent_priv->ui_manager = gtk_ui_manager_new();
1012 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
1013 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1015 /* Add common actions */
1016 gtk_action_group_add_actions (action_group,
1017 modest_msg_edit_action_entries,
1018 G_N_ELEMENTS (modest_msg_edit_action_entries),
1020 gtk_action_group_add_toggle_actions (action_group,
1021 modest_msg_edit_toggle_action_entries,
1022 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
1024 gtk_action_group_add_radio_actions (action_group,
1025 modest_msg_edit_alignment_radio_action_entries,
1026 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
1028 G_CALLBACK (modest_ui_actions_on_change_justify),
1030 gtk_action_group_add_radio_actions (action_group,
1031 modest_msg_edit_zoom_action_entries,
1032 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
1034 G_CALLBACK (modest_ui_actions_on_change_zoom),
1036 gtk_action_group_add_radio_actions (action_group,
1037 modest_msg_edit_priority_action_entries,
1038 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
1040 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
1042 gtk_action_group_add_radio_actions (action_group,
1043 modest_msg_edit_file_format_action_entries,
1044 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
1045 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
1046 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
1048 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1049 g_object_unref (action_group);
1051 /* Load the UI definition */
1052 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
1054 if (error != NULL) {
1055 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
1056 g_clear_error (&error);
1059 /* Add accelerators */
1060 gtk_window_add_accel_group (GTK_WINDOW (obj),
1061 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1064 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
1065 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1068 init_window (MODEST_MSG_EDIT_WINDOW(obj));
1070 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1072 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1074 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1075 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1077 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
1079 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
1080 if (account_pair != NULL)
1081 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
1083 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg);
1085 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1087 /* Set window icon */
1088 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
1090 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1091 g_object_unref (window_icon);
1094 /* Dim at start clipboard actions */
1095 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
1096 gtk_action_set_sensitive (action, FALSE);
1097 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
1098 gtk_action_set_sensitive (action, FALSE);
1099 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
1100 gtk_action_set_sensitive (action, FALSE);
1102 /* Update select all */
1103 update_select_all_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1104 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu");
1105 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (edit_menu_activated), obj);
1106 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu");
1107 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (view_menu_activated), obj);
1109 /* set initial state of cc and bcc */
1110 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
1111 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1112 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
1113 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
1114 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1115 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
1117 /* Setup the file format */
1118 conf = modest_runtime_get_conf ();
1119 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
1121 g_clear_error (&error);
1122 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
1124 file_format = (prefer_formatted) ?
1125 MODEST_FILE_FORMAT_FORMATTED_TEXT :
1126 MODEST_FILE_FORMAT_PLAIN_TEXT;
1127 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
1129 update_paste_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1130 priv->update_caption_visibility = TRUE;
1132 return (ModestWindow*) obj;
1136 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1138 GString **string_buffer = (GString **) user_data;
1140 *string_buffer = g_string_append (*string_buffer, buffer);
1146 * @result: A new string which should be freed with g_free().
1149 get_formatted_data (ModestMsgEditWindow *edit_window)
1151 ModestMsgEditWindowPrivate *priv;
1152 GString *string_buffer = g_string_new ("");
1154 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1156 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1158 return g_string_free (string_buffer, FALSE);
1163 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1166 const gchar *account_name;
1167 ModestMsgEditWindowPrivate *priv;
1169 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1171 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1173 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1174 g_return_val_if_fail (account_name, NULL);
1177 /* don't free these (except from) */
1178 data = g_slice_new0 (MsgData);
1179 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1181 data->account_name = g_strdup (account_name);
1182 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1183 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1184 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1185 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1186 if (priv->draft_msg) {
1187 data->draft_msg = g_object_ref (priv->draft_msg);
1189 data->draft_msg = NULL;
1192 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1194 gtk_text_buffer_get_bounds (buf, &b, &e);
1195 data->plain_body = g_strdup (gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE)); /* returns a copy */
1197 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1198 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1200 data->html_body = NULL;
1202 /* deep-copy the data */
1203 GList *cursor = priv->attachments;
1204 data->attachments = NULL;
1206 if (!(TNY_IS_MIME_PART(cursor->data))) {
1207 g_warning ("strange data in attachment list");
1208 cursor = g_list_next (cursor);
1211 data->attachments = g_list_append (data->attachments,
1212 g_object_ref (cursor->data));
1213 cursor = g_list_next (cursor);
1216 data->priority_flags = priv->priority_flags;
1223 unref_gobject (GObject *obj, gpointer data)
1225 if (!G_IS_OBJECT(obj))
1227 g_object_unref (obj);
1231 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1234 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1242 g_free (data->subject);
1243 g_free (data->plain_body);
1244 g_free (data->html_body);
1245 g_free (data->account_name);
1247 if (data->draft_msg != NULL) {
1248 g_object_unref (data->draft_msg);
1249 data->draft_msg = NULL;
1252 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1253 g_list_free (data->attachments);
1255 g_slice_free (MsgData, data);
1259 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1262 ModestMsgEditWindowPrivate *priv = NULL;
1263 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1265 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1267 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1269 return MODEST_MSG_EDIT_FORMAT_HTML;
1271 return MODEST_MSG_EDIT_FORMAT_TEXT;
1275 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1276 ModestMsgEditFormat format)
1278 ModestMsgEditWindowPrivate *priv;
1280 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1281 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1284 case MODEST_MSG_EDIT_FORMAT_HTML:
1285 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1287 case MODEST_MSG_EDIT_FORMAT_TEXT:
1288 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1291 g_return_if_reached ();
1295 ModestMsgEditFormatState *
1296 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1298 ModestMsgEditFormatState *format_state = NULL;
1299 ModestMsgEditWindowPrivate *priv;
1300 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1302 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1303 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1305 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1307 format_state = g_new0 (ModestMsgEditFormatState, 1);
1308 format_state->bold = buffer_format->bold&0x1;
1309 format_state->italics = buffer_format->italic&0x1;
1310 format_state->bullet = buffer_format->bullet&0x1;
1311 format_state->color = buffer_format->color;
1312 format_state->font_size = buffer_format->font_size;
1313 format_state->font_family = wp_get_font_name (buffer_format->font);
1314 format_state->justification = buffer_format->justification;
1315 g_free (buffer_format);
1317 return format_state;
1322 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1323 const ModestMsgEditFormatState *format_state)
1325 ModestMsgEditWindowPrivate *priv;
1326 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1327 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1328 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1329 g_return_if_fail (format_state != NULL);
1331 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1332 gtk_widget_grab_focus (priv->msg_body);
1333 buffer_format->bold = (format_state->bold != FALSE);
1334 buffer_format->italic = (format_state->italics != FALSE);
1335 buffer_format->color = format_state->color;
1336 buffer_format->font_size = format_state->font_size;
1337 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1338 buffer_format->justification = format_state->justification;
1339 buffer_format->bullet = format_state->bullet;
1341 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1343 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1344 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1345 buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
1346 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1347 buffer_format->cs.font = (buffer_format->font != current_format->font);
1348 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1349 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1351 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1352 if (buffer_format->cs.bold) {
1353 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1355 if (buffer_format->cs.italic) {
1356 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1358 if (buffer_format->cs.color) {
1359 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1361 if (buffer_format->cs.font_size) {
1362 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1364 if (buffer_format->cs.justification) {
1365 switch (buffer_format->justification) {
1366 case GTK_JUSTIFY_LEFT:
1367 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1369 case GTK_JUSTIFY_CENTER:
1370 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1372 case GTK_JUSTIFY_RIGHT:
1373 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1380 if (buffer_format->cs.font) {
1381 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1383 if (buffer_format->cs.bullet) {
1384 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((int)buffer_format->bullet));
1386 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1387 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1389 g_free (current_format);
1394 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1396 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1398 ModestWindowPrivate *parent_priv;
1399 ModestMsgEditWindowPrivate *priv;
1400 GtkWidget *new_size_menuitem;
1401 GtkWidget *new_font_menuitem;
1403 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1404 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1406 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1407 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1408 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1409 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1411 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1412 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1413 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1416 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1418 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1419 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1421 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1422 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1424 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1425 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1427 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1428 G_CALLBACK (modest_msg_edit_window_color_button_change),
1430 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1431 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1432 G_CALLBACK (modest_msg_edit_window_color_button_change),
1435 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1436 buffer_format->font_size))->data);
1437 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1441 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1442 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1443 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1445 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1446 G_CALLBACK (modest_msg_edit_window_size_change),
1448 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1449 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1450 G_CALLBACK (modest_msg_edit_window_size_change),
1454 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1455 buffer_format->font))->data);
1456 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1460 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1461 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1462 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1464 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1465 G_CALLBACK (modest_msg_edit_window_font_change),
1467 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1468 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1469 G_CALLBACK (modest_msg_edit_window_font_change),
1473 g_free (buffer_format);
1479 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1482 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1483 ModestMsgEditWindowPrivate *priv;
1484 GtkWidget *dialog = NULL;
1486 const GdkColor *new_color = NULL;
1488 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1489 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1491 #ifdef MODEST_HILDON_VERSION_0
1492 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1493 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1495 dialog = hildon_color_chooser_new ();
1496 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1497 #endif /*MODEST_HILDON_VERSION_0*/
1498 g_free (buffer_format);
1500 response = gtk_dialog_run (GTK_DIALOG (dialog));
1502 case GTK_RESPONSE_OK: {
1503 #ifdef MODEST_HILDON_VERSION_0
1504 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1507 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1509 #endif /*MODEST_HILDON_VERSION_0*/
1516 gtk_widget_destroy (dialog);
1518 if (new_color != NULL)
1519 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1524 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1527 ModestMsgEditWindowPrivate *priv;
1528 GtkWidget *dialog = NULL;
1530 GdkColor *old_color = NULL;
1531 const GdkColor *new_color = NULL;
1533 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1534 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1536 #ifdef MODEST_HILDON_VERSION_0
1537 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1538 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1540 dialog = hildon_color_chooser_new ();
1541 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1542 #endif /*MODEST_HILDON_VERSION_9*/
1544 response = gtk_dialog_run (GTK_DIALOG (dialog));
1546 case GTK_RESPONSE_OK: {
1547 #ifdef MODEST_HILDON_VERSION_0
1548 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1551 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1553 #endif /*MODEST_HILDON_VERSION_0*/
1559 gtk_widget_destroy (dialog);
1561 if (new_color != NULL)
1562 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1566 static TnyStream* create_stream_for_uri (const gchar* uri)
1571 TnyStream *result = NULL;
1573 GnomeVFSHandle *handle = NULL;
1574 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1575 if (test == GNOME_VFS_OK) {
1576 /* Create the tinymail stream: */
1577 /* Presumably tinymai will call gnome_vfs_close (handle) later. */
1578 result = TNY_STREAM (tny_vfs_stream_new (handle));
1585 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1588 ModestMsgEditWindowPrivate *priv;
1589 GtkWidget *dialog = NULL;
1591 GSList *uris = NULL;
1592 GSList *uri_node = NULL;
1594 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1596 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1597 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1598 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1600 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1602 response = gtk_dialog_run (GTK_DIALOG (dialog));
1604 case GTK_RESPONSE_OK:
1605 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1610 gtk_widget_destroy (dialog);
1612 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1614 GnomeVFSHandle *handle = NULL;
1615 GnomeVFSResult result;
1616 GtkTextIter position;
1617 GtkTextMark *insert_mark;
1619 uri = (const gchar *) uri_node->data;
1620 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1621 if (result == GNOME_VFS_OK) {
1623 GnomeVFSFileInfo info;
1624 gchar *filename, *basename, *escaped_filename;
1625 TnyMimePart *mime_part;
1627 const gchar *mime_type = NULL;
1628 GnomeVFSURI *vfs_uri;
1630 vfs_uri = gnome_vfs_uri_new (uri);
1632 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1633 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1634 g_free (escaped_filename);
1635 gnome_vfs_uri_unref (vfs_uri);
1637 if (gnome_vfs_get_file_info (uri, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
1638 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1640 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1642 mime_part = tny_platform_factory_new_mime_part
1643 (modest_runtime_get_platform_factory ());
1645 TnyStream *stream = create_stream_for_uri (uri);
1646 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1648 content_id = g_strdup_printf ("%d", priv->last_cid);
1649 tny_mime_part_set_content_id (mime_part, content_id);
1650 g_free (content_id);
1653 basename = g_path_get_basename (filename);
1654 tny_mime_part_set_filename (mime_part, basename);
1657 pixbuf = pixbuf_from_stream (stream, mime_type);
1659 if (pixbuf != NULL) {
1660 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1661 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1662 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1665 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1666 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1668 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1669 gtk_widget_show_all (priv->attachments_caption);
1670 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1680 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
1683 ModestMsgEditWindowPrivate *priv;
1684 GtkWidget *dialog = NULL;
1686 GSList *uris = NULL;
1689 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1691 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1692 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
1693 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1695 response = gtk_dialog_run (GTK_DIALOG (dialog));
1697 case GTK_RESPONSE_OK:
1698 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1703 gtk_widget_destroy (dialog);
1705 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1706 const gchar *uri = (const gchar *) uri_node->data;
1707 modest_msg_edit_window_attach_file_one (window, uri);
1709 g_slist_foreach (uris, (GFunc) g_free, NULL);
1710 g_slist_free (uris);
1714 modest_msg_edit_window_attach_file_one (
1715 ModestMsgEditWindow *window,
1718 g_return_if_fail (window);
1719 g_return_if_fail (uri);
1721 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1724 GnomeVFSHandle *handle = NULL;
1725 GnomeVFSResult result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1726 if (result == GNOME_VFS_OK) {
1727 TnyMimePart *mime_part;
1729 const gchar *mime_type = NULL;
1731 gchar *escaped_filename;
1734 GnomeVFSFileInfo info;
1735 GnomeVFSURI *vfs_uri;
1737 vfs_uri = gnome_vfs_uri_new (uri);
1740 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1741 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1742 g_free (escaped_filename);
1743 gnome_vfs_uri_unref (vfs_uri);
1745 if (gnome_vfs_get_file_info (uri,
1747 GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
1748 GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1750 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1751 mime_part = tny_platform_factory_new_mime_part
1752 (modest_runtime_get_platform_factory ());
1753 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1755 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1757 content_id = g_strdup_printf ("%d", priv->last_cid);
1758 tny_mime_part_set_content_id (mime_part, content_id);
1759 g_free (content_id);
1762 basename = g_path_get_basename (filename);
1763 tny_mime_part_set_filename (mime_part, basename);
1766 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1767 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1769 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1770 gtk_widget_show_all (priv->attachments_caption);
1771 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1777 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1780 ModestMsgEditWindowPrivate *priv;
1781 gboolean clean_list = FALSE;
1783 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1784 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1786 if (att_list == NULL) {
1787 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1791 if (att_list == NULL) {
1792 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1794 GtkWidget *confirmation_dialog = NULL;
1795 gboolean dialog_response;
1797 gchar *message = NULL;
1798 const gchar *filename = NULL;
1800 if (att_list->next == NULL) {
1801 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1805 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1806 att_list->next == NULL), filename);
1807 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1809 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1810 gtk_widget_destroy (confirmation_dialog);
1811 if (!dialog_response) {
1813 g_list_free (att_list);
1816 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1818 for (node = att_list; node != NULL; node = g_list_next (node)) {
1819 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1820 const gchar *att_id;
1821 priv->attachments = g_list_remove (priv->attachments, mime_part);
1823 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1825 if (priv->attachments == NULL)
1826 gtk_widget_hide (priv->attachments_caption);
1827 att_id = tny_mime_part_get_content_id (mime_part);
1829 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1831 g_object_unref (mime_part);
1832 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1837 g_list_free (att_list);
1841 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1844 ModestMsgEditWindowPrivate *priv;
1845 GdkColor *new_color;
1846 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1848 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1849 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1852 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1854 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1856 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1858 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1863 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1866 ModestMsgEditWindowPrivate *priv;
1867 gint new_size_index;
1868 ModestMsgEditWindow *window;
1871 window = MODEST_MSG_EDIT_WINDOW (userdata);
1872 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1873 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1875 if (gtk_check_menu_item_get_active (menu_item)) {
1877 WPTextBufferFormat format;
1879 memset (&format, 0, sizeof (format));
1880 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1882 label = gtk_bin_get_child (GTK_BIN (menu_item));
1884 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1885 format.cs.font_size = TRUE;
1886 format.cs.text_position = TRUE;
1887 format.cs.font = TRUE;
1888 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1889 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1891 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1892 (gpointer) wp_get_font_size_index (new_size_index, 12)))
1893 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1895 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1896 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1897 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1903 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1906 ModestMsgEditWindowPrivate *priv;
1907 gint new_font_index;
1908 ModestMsgEditWindow *window;
1911 window = MODEST_MSG_EDIT_WINDOW (userdata);
1912 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1913 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1915 if (gtk_check_menu_item_get_active (menu_item)) {
1918 label = gtk_bin_get_child (GTK_BIN (menu_item));
1920 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1922 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1923 (gpointer) new_font_index))
1924 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1926 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1927 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1928 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1934 modest_msg_edit_window_set_zoom (ModestWindow *window,
1937 ModestMsgEditWindowPrivate *priv;
1938 ModestWindowPrivate *parent_priv;
1939 GtkRadioAction *zoom_radio_action;
1941 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1943 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1944 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1945 priv->zoom_level = zoom;
1946 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom*DEFAULT_FONT_SCALE);
1948 /* Zoom level menu options should be updated with the current zoom level */
1949 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1950 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1951 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1952 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1953 /* FIXME: Not availible before Gtk 2.10 */
1955 gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
1960 modest_msg_edit_window_get_zoom (ModestWindow *window)
1962 ModestMsgEditWindowPrivate *priv;
1964 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1966 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1967 return priv->zoom_level;
1971 zoom_allowed (ModestMsgEditWindow *window)
1975 focus = gtk_window_get_focus (GTK_WINDOW (window));
1976 return (focus != NULL && WP_IS_TEXT_VIEW (focus));
1980 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1982 ModestWindowPrivate *parent_priv;
1983 GtkRadioAction *zoom_radio_action;
1984 GSList *group, *node;
1986 /* First we check if the text view is focused. If not, zooming is not allowed */
1987 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1988 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1992 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1993 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1994 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1996 group = gtk_radio_action_get_group (zoom_radio_action);
1998 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1999 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
2003 for (node = group; node != NULL; node = g_slist_next (node)) {
2004 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
2005 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
2013 modest_msg_edit_window_zoom_minus (ModestWindow *window)
2015 ModestWindowPrivate *parent_priv;
2016 GtkRadioAction *zoom_radio_action;
2017 GSList *group, *node;
2019 /* First we check if the text view is focused. If not, zooming is not allowed */
2020 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2021 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2025 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2026 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2027 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2029 group = gtk_radio_action_get_group (zoom_radio_action);
2031 for (node = group; node != NULL; node = g_slist_next (node)) {
2032 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
2033 if (node->next != NULL) {
2034 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
2037 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
2045 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2047 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2048 ModestWindowPrivate *parent_priv;
2049 ModestWindowMgr *mgr;
2050 gboolean is_fullscreen;
2051 GtkAction *fs_toggle_action;
2054 mgr = modest_runtime_get_window_mgr ();
2055 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2057 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2059 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2060 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2061 if (is_fullscreen != active)
2062 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2070 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
2072 ModestWindowPrivate *parent_priv;
2073 GtkAction *fs_toggle_action;
2076 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2078 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2079 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
2080 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
2084 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2087 ModestMsgEditWindowPrivate *priv = NULL;
2088 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2090 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2091 if (!priv->update_caption_visibility)
2094 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2096 gtk_widget_show (priv->cc_caption);
2098 gtk_widget_hide (priv->cc_caption);
2100 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2104 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2107 ModestMsgEditWindowPrivate *priv = NULL;
2108 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2110 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2111 if (!priv->update_caption_visibility)
2114 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2116 gtk_widget_show (priv->bcc_caption);
2118 gtk_widget_hide (priv->bcc_caption);
2120 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2124 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2125 ModestRecptEditor *editor)
2127 ModestMsgEditWindowPrivate *priv;
2129 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2130 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2131 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2133 if (editor == NULL) {
2134 GtkWidget *view_focus;
2135 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2137 /* This code should be kept in sync with ModestRecptEditor. The
2138 textview inside the recpt editor is the one that really gets the
2139 focus. As it's inside a scrolled window, and this one inside the
2140 hbox recpt editor inherits from, we'll need to go up in the
2141 hierarchy to know if the text view is part of the recpt editor
2142 or if it's a different text entry */
2144 if (gtk_widget_get_parent (view_focus)) {
2145 GtkWidget *first_parent;
2147 first_parent = gtk_widget_get_parent (view_focus);
2148 if (gtk_widget_get_parent (first_parent) &&
2149 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2150 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2155 editor = MODEST_RECPT_EDITOR (priv->to_field);
2159 modest_address_book_select_addresses (editor);
2164 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2166 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2168 modest_msg_edit_window_open_addressbook (window, NULL);
2172 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2173 gboolean show_toolbar)
2175 ModestWindowPrivate *parent_priv;
2177 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2178 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2180 /* FIXME: we can not just use the code of
2181 modest_msg_edit_window_setup_toolbar because it has a
2182 mixture of both initialization and creation code. */
2185 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2187 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2191 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2192 TnyHeaderFlags priority_flags)
2194 ModestMsgEditWindowPrivate *priv;
2195 ModestWindowPrivate *parent_priv;
2197 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2199 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2200 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2201 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2203 if (priv->priority_flags != priority_flags) {
2204 GtkAction *priority_action = NULL;
2206 priv->priority_flags = priority_flags;
2208 switch (priority_flags) {
2209 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2210 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2211 gtk_widget_show (priv->priority_icon);
2212 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2213 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2215 case TNY_HEADER_FLAG_LOW_PRIORITY:
2216 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2217 gtk_widget_show (priv->priority_icon);
2218 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2219 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2222 gtk_widget_hide (priv->priority_icon);
2223 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2224 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2227 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2228 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2233 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2236 ModestMsgEditWindowPrivate *priv;
2237 ModestWindowPrivate *parent_priv;
2238 gint current_format;
2240 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2242 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2243 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2245 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2246 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2248 if (current_format != file_format) {
2249 switch (file_format) {
2250 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2251 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2253 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2257 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2258 response = gtk_dialog_run (GTK_DIALOG (dialog));
2259 gtk_widget_destroy (dialog);
2260 if (response == GTK_RESPONSE_OK) {
2261 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2263 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2264 modest_maemo_toggle_action_set_active_block_notify (action, TRUE);
2269 update_dimmed (window);
2274 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2277 ModestMsgEditWindowPrivate *priv;
2278 WPTextBufferFormat oldfmt, fmt;
2279 gint old_position = 0;
2283 GdkColor *color = NULL;
2284 gboolean bold, bold_set, italic, italic_set;
2285 gboolean underline, underline_set;
2286 gboolean strikethrough, strikethrough_set;
2287 gboolean position_set;
2288 gboolean font_size_set, font_set, color_set;
2291 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2292 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2294 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2296 /* First we get the currently selected font information */
2297 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2298 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2300 switch (oldfmt.text_position) {
2301 case TEXT_POSITION_NORMAL:
2304 case TEXT_POSITION_SUPERSCRIPT:
2312 g_object_set (G_OBJECT (dialog),
2313 "bold", oldfmt.bold != FALSE,
2314 "bold-set", !oldfmt.cs.bold,
2315 "underline", oldfmt.underline != FALSE,
2316 "underline-set", !oldfmt.cs.underline,
2317 "italic", oldfmt.italic != FALSE,
2318 "italic-set", !oldfmt.cs.italic,
2319 "strikethrough", oldfmt.strikethrough != FALSE,
2320 "strikethrough-set", !oldfmt.cs.strikethrough,
2321 "color", &oldfmt.color,
2322 "color-set", !oldfmt.cs.color,
2323 "size", wp_font_size[oldfmt.font_size],
2324 "size-set", !oldfmt.cs.font_size,
2325 "position", old_position,
2326 "position-set", !oldfmt.cs.text_position,
2327 "family", wp_get_font_name (oldfmt.font),
2328 "family-set", !oldfmt.cs.font,
2331 gtk_widget_show_all (dialog);
2332 response = gtk_dialog_run (GTK_DIALOG (dialog));
2333 if (response == GTK_RESPONSE_OK) {
2335 g_object_get( dialog,
2337 "bold-set", &bold_set,
2338 "underline", &underline,
2339 "underline-set", &underline_set,
2341 "italic-set", &italic_set,
2342 "strikethrough", &strikethrough,
2343 "strikethrough-set", &strikethrough_set,
2345 "color-set", &color_set,
2347 "size-set", &font_size_set,
2348 "family", &font_name,
2349 "family-set", &font_set,
2350 "position", &position,
2351 "position-set", &position_set,
2356 if (response == GTK_RESPONSE_OK) {
2357 memset(&fmt, 0, sizeof(fmt));
2363 fmt.italic = italic;
2364 fmt.cs.italic = TRUE;
2366 if (underline_set) {
2367 fmt.underline = underline;
2368 fmt.cs.underline = TRUE;
2370 if (strikethrough_set) {
2371 fmt.strikethrough = strikethrough;
2372 fmt.cs.strikethrough = TRUE;
2377 ? TEXT_POSITION_NORMAL
2378 : ( ( position == 1 )
2379 ? TEXT_POSITION_SUPERSCRIPT
2380 : TEXT_POSITION_SUBSCRIPT );
2381 fmt.cs.text_position = TRUE;
2385 fmt.cs.color = TRUE;
2388 fmt.font = wp_get_font_index(font_name,
2393 if (font_size_set) {
2394 fmt.font_size = wp_get_font_size_index(
2395 font_size, DEFAULT_FONT_SIZE);
2396 fmt.cs.font_size = TRUE;
2398 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2400 gtk_widget_destroy (dialog);
2402 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2406 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2408 ModestMsgEditWindowPrivate *priv;
2410 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2411 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2413 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2415 update_dimmed (window);
2420 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2422 ModestMsgEditWindowPrivate *priv;
2424 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2425 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2427 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2429 update_dimmed (window);
2434 update_dimmed (ModestMsgEditWindow *window)
2436 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2437 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2441 gboolean editor_focused;
2443 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2444 editor_focused = gtk_widget_is_focus (priv->msg_body);
2446 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2447 gtk_action_set_sensitive (action, rich_text && editor_focused);
2448 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2449 gtk_action_set_sensitive (action, rich_text && editor_focused);
2450 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2451 gtk_action_set_sensitive (action, rich_text && editor_focused);
2452 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2453 gtk_action_set_sensitive (action, rich_text && editor_focused);
2454 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2455 gtk_action_set_sensitive (action, rich_text && editor_focused);
2456 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2457 gtk_action_set_sensitive (action, rich_text && editor_focused);
2458 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2459 gtk_action_set_sensitive (action, rich_text && editor_focused);
2460 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2461 gtk_action_set_sensitive (action, rich_text && editor_focused);
2462 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2463 gtk_action_set_sensitive (action, rich_text && editor_focused);
2464 widget = priv->font_color_button;
2465 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2466 widget = priv->font_size_toolitem;
2467 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2468 widget = priv->font_face_toolitem;
2469 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2473 setup_insensitive_handlers (ModestMsgEditWindow *window)
2475 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2476 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2479 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2480 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2481 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2482 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2483 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2484 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2485 widget = priv->font_color_button;
2486 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2487 widget = priv->font_size_toolitem;
2488 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2489 widget = priv->font_face_toolitem;
2490 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2495 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2497 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2500 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2501 gtk_action_set_sensitive (action, can_undo);
2505 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2507 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2510 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/RedoMenu");
2511 gtk_action_set_sensitive (action, can_redo);
2515 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2518 GtkTextIter match_start, match_end;
2520 if (image_id == NULL)
2523 gtk_text_buffer_get_start_iter (buffer, &iter);
2525 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2526 GSList *tags = gtk_text_iter_get_tags (&match_start);
2528 for (node = tags; node != NULL; node = g_slist_next (node)) {
2529 GtkTextTag *tag = (GtkTextTag *) node->data;
2530 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2531 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2532 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2534 offset = gtk_text_iter_get_offset (&match_start);
2535 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2536 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2540 gtk_text_iter_forward_char (&iter);
2545 msg_body_focus (GtkWidget *focus,
2546 GdkEventFocus *event,
2550 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2555 recpt_field_changed (GtkTextBuffer *buffer,
2556 ModestMsgEditWindow *editor)
2558 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2559 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2560 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2561 gboolean dim = FALSE;
2564 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2565 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2566 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2568 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2569 gtk_text_buffer_get_char_count (cc_buffer) +
2570 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2572 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2573 gtk_action_set_sensitive (action, !dim);
2574 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2575 gtk_action_set_sensitive (action, !dim);
2579 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2581 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2585 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2587 gboolean rich_text, editor_focused;
2589 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2590 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2591 editor_focused = gtk_widget_is_focus (priv->msg_body);
2594 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2595 else if (!editor_focused)
2596 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2600 reset_modified (ModestMsgEditWindow *editor)
2602 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2603 GtkTextBuffer *buffer;
2605 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2606 gtk_text_buffer_set_modified (buffer, FALSE);
2607 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2608 gtk_text_buffer_set_modified (buffer, FALSE);
2609 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2610 gtk_text_buffer_set_modified (buffer, FALSE);
2611 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2615 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2617 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2618 GtkTextBuffer *buffer;
2620 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2621 if (gtk_text_buffer_get_modified (buffer))
2623 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2624 if (gtk_text_buffer_get_modified (buffer))
2626 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2627 if (gtk_text_buffer_get_modified (buffer))
2629 if (gtk_text_buffer_get_modified (priv->text_buffer))
2636 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
2638 ModestMsgEditWindowPrivate *priv = NULL;
2640 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2641 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2643 /* check if there's no recipient added */
2644 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2645 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2646 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2647 /* no recipient contents, then select contacts */
2648 modest_msg_edit_window_open_addressbook (window, NULL);
2652 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook))
2654 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook))
2656 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook))
2659 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2666 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2667 ModestMsgEditWindow *window)
2669 modest_msg_edit_window_offer_attach_file (window);
2673 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2675 ModestMsgEditWindow *window)
2677 ModestWindowPrivate *parent_priv;
2678 ModestMsgEditWindowPrivate *priv;
2680 gboolean has_selection;
2682 GList *selected_attachments = NULL;
2683 gint n_att_selected = 0;
2685 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2686 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2688 if (!GTK_WIDGET_VISIBLE (window))
2690 has_selection = gtk_clipboard_wait_for_targets (clipboard, NULL, NULL);
2691 focused = gtk_window_get_focus (GTK_WINDOW (window));
2693 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2694 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2695 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2696 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2698 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2699 n_att_selected = g_list_length (selected_attachments);
2700 g_list_free (selected_attachments);
2702 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2703 gtk_action_set_sensitive (action, n_att_selected == 1);
2705 update_paste_dimming (window);
2709 update_window_title (ModestMsgEditWindow *window)
2711 ModestMsgEditWindowPrivate *priv = NULL;
2712 const gchar *subject;
2714 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2715 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2716 if (subject == NULL || subject[0] == '\0')
2717 subject = _("mail_va_new_email");
2719 gtk_window_set_title (GTK_WINDOW (window), subject);
2724 subject_field_changed (GtkEditable *editable,
2725 ModestMsgEditWindow *window)
2727 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2728 update_window_title (window);
2729 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2733 message_is_empty (ModestMsgEditWindow *window)
2735 ModestMsgEditWindowPrivate *priv = NULL;
2737 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2738 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2740 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
2741 * so we can ignore markup.
2743 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
2746 count = gtk_text_buffer_get_char_count (buf);
2752 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2755 ModestMsgEditWindowPrivate *priv = NULL;
2757 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2758 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2760 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2763 gtk_widget_show_all (priv->find_toolbar);
2764 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2766 gtk_widget_hide_all (priv->find_toolbar);
2767 gtk_widget_grab_focus (priv->msg_body);
2773 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2775 GtkTextIter *match_start,
2776 GtkTextIter *match_end)
2778 GtkTextIter end_iter;
2779 gchar *str_casefold;
2782 gchar *range_casefold;
2785 gboolean result = FALSE;
2792 gtk_text_iter_forward_to_end (&end_iter);
2794 str_casefold = g_utf8_casefold (str, -1);
2795 str_chars_n = strlen (str);
2797 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2798 range_casefold = g_utf8_casefold (range_text, -1);
2799 range_chars_n = strlen (range_casefold);
2801 if (range_chars_n < str_chars_n) {
2802 g_free (str_casefold);
2803 g_free (range_text);
2804 g_free (range_casefold);
2808 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2809 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2810 if (!g_utf8_collate (range_subtext, str_casefold)) {
2811 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2813 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2814 match_start, match_end, NULL);
2815 g_free (found_text);
2817 g_free (range_subtext);
2821 g_free (str_casefold);
2822 g_free (range_text);
2823 g_free (range_casefold);
2830 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2831 ModestMsgEditWindow *window)
2833 gchar *current_search = NULL;
2834 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2836 GtkTextIter selection_start, selection_end;
2837 GtkTextIter match_start, match_end;
2838 gboolean continue_search = FALSE;
2840 if (message_is_empty (window)) {
2841 g_free (priv->last_search);
2842 priv->last_search = NULL;
2843 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
2847 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2848 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2849 g_free (current_search);
2850 g_free (priv->last_search);
2851 priv->last_search = NULL;
2852 /* Information banner about empty search */
2853 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2857 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2858 continue_search = TRUE;
2860 g_free (priv->last_search);
2861 priv->last_search = g_strdup (current_search);
2864 if (continue_search) {
2865 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2866 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2867 &match_start, &match_end);
2869 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2871 GtkTextIter buffer_start;
2872 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2873 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2874 &match_start, &match_end);
2876 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2879 /* Mark as selected the string found in search */
2881 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2882 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2884 g_free (priv->last_search);
2885 priv->last_search = NULL;
2887 g_free (current_search);
2891 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2892 ModestMsgEditWindow *window)
2894 GtkToggleAction *toggle;
2895 ModestWindowPrivate *parent_priv;
2896 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2898 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2899 gtk_toggle_action_set_active (toggle, FALSE);
2904 update_paste_dimming (ModestMsgEditWindow *window)
2906 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2907 GtkAction *action = NULL;
2908 GtkClipboard *clipboard = NULL;
2909 ModestEmailClipboard *e_clipboard;
2913 focused = gtk_window_get_focus (GTK_WINDOW (window));
2915 e_clipboard = modest_runtime_get_email_clipboard ();
2916 if (!modest_email_clipboard_cleared (e_clipboard)) {
2919 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2920 active = gtk_clipboard_wait_is_text_available (clipboard);
2924 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2928 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2929 gtk_action_set_sensitive (action, active);
2934 update_select_all_dimming (ModestMsgEditWindow *window)
2937 gboolean dimmed = FALSE;
2939 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2941 focused = gtk_window_get_focus (GTK_WINDOW (window));
2942 if (GTK_IS_ENTRY (focused)) {
2943 const gchar *current_text;
2944 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
2945 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
2946 } else if (GTK_IS_TEXT_VIEW (focused)) {
2947 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
2948 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
2949 } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
2952 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
2953 gtk_action_set_sensitive (action, !dimmed);
2957 update_zoom_dimming (ModestMsgEditWindow *window)
2960 gboolean dimmed = FALSE;
2962 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2964 focused = gtk_window_get_focus (GTK_WINDOW (window));
2965 dimmed = ! WP_IS_TEXT_VIEW (focused);
2966 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2967 gtk_action_set_sensitive (action, !dimmed);
2971 edit_menu_activated (GtkAction *action,
2974 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2976 update_select_all_dimming (window);
2977 update_paste_dimming (window);
2980 view_menu_activated (GtkAction *action,
2983 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2985 update_zoom_dimming (window);
2989 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
2991 ModestMsgEditWindowPrivate *priv;
2993 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
2998 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3001 ModestMsgEditWindowPrivate *priv;
3003 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3009 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3012 ModestMsgEditWindowPrivate *priv;
3013 TnyHeader *header = NULL;
3015 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3016 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3018 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3019 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3021 if (priv->draft_msg != NULL) {
3022 header = tny_msg_get_header (priv->draft_msg);
3023 if (TNY_IS_HEADER (header)) {
3024 modest_window_mgr_unregister_header (mgr, header);
3026 g_object_unref (priv->draft_msg);
3029 if (draft != NULL) {
3030 g_object_ref (draft);
3031 header = tny_msg_get_header (draft);
3032 if (TNY_IS_HEADER (header))
3033 modest_window_mgr_register_header (mgr, header);
3036 priv->draft_msg = draft;
3040 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3041 GtkTextIter *start, GtkTextIter *end,
3044 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3045 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3048 if (tag == NULL+13) return;
3049 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3050 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3051 replace_with_attachments (window, priv->attachments);
3056 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3059 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3061 g_return_if_fail (TNY_IS_MIME_PART (part));
3062 priv->attachments = g_list_prepend (priv->attachments, part);
3063 g_object_ref (part);
3064 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part);
3065 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3066 gtk_widget_show_all (priv->attachments_caption);
3067 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);