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 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
667 g_object_unref (pixbuf);
674 update_last_cid (ModestMsgEditWindow *self, GList *attachments)
677 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
679 for (node = attachments; node != NULL; node = g_list_next (node)) {
680 TnyMimePart *part = (TnyMimePart *) node->data;
681 const gchar *cid = tny_mime_part_get_content_id (part);
683 char *invalid = NULL;
684 gint int_cid = strtol (cid, &invalid, 10);
685 if ((invalid != NULL) && (*invalid == '\0') && (int_cid > priv->last_cid)) {
686 priv->last_cid = int_cid;
694 set_msg (ModestMsgEditWindow *self, TnyMsg *msg)
697 const gchar *to, *cc, *bcc, *subject;
699 ModestMsgEditWindowPrivate *priv;
701 TnyHeaderFlags priority_flags;
702 TnyFolder *msg_folder;
704 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
705 g_return_if_fail (TNY_IS_MSG (msg));
707 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
709 header = tny_msg_get_header (msg);
710 to = tny_header_get_to (header);
711 cc = tny_header_get_cc (header);
712 bcc = tny_header_get_bcc (header);
713 subject = tny_header_get_subject (header);
714 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
717 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
719 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
720 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
721 gtk_widget_show (priv->cc_caption);
722 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
723 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
724 gtk_widget_hide (priv->cc_caption);
727 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
728 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
729 gtk_widget_show (priv->bcc_caption);
730 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
731 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
732 gtk_widget_hide (priv->bcc_caption);
735 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
736 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
739 update_window_title (self);
741 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
742 body = modest_tny_msg_get_body (msg, TRUE);
744 if ((body == NULL)||(body[0] == '\0')) {
746 body = modest_text_utils_convert_to_html ("");
748 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
749 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
752 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
755 /* Get the default format required from configuration */
756 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
757 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
760 /* Set the default focus depending on having already a To: field or not */
761 if ((!to)||(*to == '\0')) {
762 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
764 gtk_widget_grab_focus (priv->msg_body);
767 /* TODO: lower priority, select in the From: combo to the
768 value that comes from msg <- not sure, should it be
771 /* Add attachments to the view */
772 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
773 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
774 if (priv->attachments == NULL) {
775 gtk_widget_hide (priv->attachments_caption);
777 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
778 gtk_widget_show_all (priv->attachments_caption);
779 replace_with_attachments (self, priv->attachments);
781 update_last_cid (self, priv->attachments);
783 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
785 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
786 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
788 reset_modified (self);
790 update_dimmed (self);
791 text_buffer_can_undo (priv->text_buffer, FALSE, self);
792 text_buffer_can_redo (priv->text_buffer, FALSE, self);
794 /* we should set a reference to the incoming message if it is a draft */
795 msg_folder = tny_msg_get_folder (msg);
797 if (modest_tny_folder_is_local_folder (msg_folder) &&
798 modest_tny_folder_get_local_or_mmc_folder_type (msg_folder) == TNY_FOLDER_TYPE_DRAFTS)
799 priv->draft_msg = g_object_ref(msg);
800 g_object_unref (msg_folder);
805 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
808 GList *item_children, *node;
809 GtkWidget *bin_child;
811 bin_child = gtk_bin_get_child (GTK_BIN(item));
813 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
815 for (node = item_children; node != NULL; node = g_list_next (node)) {
816 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
817 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
820 g_list_free (item_children);
824 menu_tool_button_dont_expand (GtkMenuToolButton *item)
827 GList *item_children, *node;
829 box = gtk_bin_get_child (GTK_BIN (item));
830 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
831 item_children = gtk_container_get_children (GTK_CONTAINER (box));
833 for (node = item_children; node != NULL; node = g_list_next (node)) {
834 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
835 if (GTK_IS_TOGGLE_BUTTON (node->data))
836 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
837 else if (GTK_IS_BUTTON (node->data))
838 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
840 g_list_free (item_children);
845 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
847 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
848 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
849 GtkWidget *placeholder;
850 GtkWidget *tool_item;
855 GtkWidget *sizes_menu;
856 GtkWidget *fonts_menu;
857 GSList *radio_group = NULL;
862 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
863 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
865 /* should we hide the toolbar? */
866 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
867 gtk_widget_hide (parent_priv->toolbar);
869 /* Font color placeholder */
870 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
871 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
874 tool_item = GTK_WIDGET (gtk_tool_item_new ());
875 priv->font_color_button = hildon_color_button_new ();
876 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
877 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
878 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
879 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
880 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
881 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
882 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
884 /* Font size and face placeholder */
885 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
886 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
888 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
889 priv->size_tool_button_label = gtk_label_new (NULL);
890 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
891 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
892 size_text,"</span>", NULL);
893 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
895 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
896 sizes_menu = gtk_menu_new ();
897 priv->size_items_group = NULL;
899 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
900 GtkWidget *size_menu_item;
902 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
903 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
904 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
905 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
906 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
907 gtk_widget_show (size_menu_item);
909 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
913 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
914 GtkWidget *item = (GtkWidget *) node->data;
915 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
919 priv->size_items_group = g_slist_reverse (priv->size_items_group);
920 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
921 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
922 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
923 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
924 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
925 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
926 priv->font_size_toolitem = tool_item;
929 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
930 priv->font_tool_button_label = gtk_label_new (NULL);
931 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
932 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
934 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
935 fonts_menu = gtk_menu_new ();
936 priv->font_items_group = NULL;
938 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
939 GtkWidget *font_menu_item;
940 GtkWidget *child_label;
942 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
943 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
944 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
945 wp_get_font_name (font_index), "</span>", NULL);
946 gtk_label_set_markup (GTK_LABEL (child_label), markup);
949 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
950 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
951 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
952 gtk_widget_show (font_menu_item);
954 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
957 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
958 GtkWidget *item = (GtkWidget *) node->data;
959 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
962 priv->font_items_group = g_slist_reverse (priv->font_items_group);
963 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
964 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
965 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
966 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
967 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
968 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
969 priv->font_face_toolitem = tool_item;
971 /* Set expand and homogeneous for remaining items */
972 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
973 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
974 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
975 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
976 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
977 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
978 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
979 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
980 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
988 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name)
991 ModestWindowPrivate *parent_priv;
992 ModestMsgEditWindowPrivate *priv;
993 GtkActionGroup *action_group;
994 GError *error = NULL;
995 GdkPixbuf *window_icon = NULL;
998 gboolean prefer_formatted;
1000 ModestPair *account_pair = NULL;
1002 g_return_val_if_fail (msg, NULL);
1003 g_return_val_if_fail (account_name, NULL);
1005 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
1007 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1008 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1010 parent_priv->ui_manager = gtk_ui_manager_new();
1011 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
1012 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1014 /* Add common actions */
1015 gtk_action_group_add_actions (action_group,
1016 modest_msg_edit_action_entries,
1017 G_N_ELEMENTS (modest_msg_edit_action_entries),
1019 gtk_action_group_add_toggle_actions (action_group,
1020 modest_msg_edit_toggle_action_entries,
1021 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
1023 gtk_action_group_add_radio_actions (action_group,
1024 modest_msg_edit_alignment_radio_action_entries,
1025 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
1027 G_CALLBACK (modest_ui_actions_on_change_justify),
1029 gtk_action_group_add_radio_actions (action_group,
1030 modest_msg_edit_zoom_action_entries,
1031 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
1033 G_CALLBACK (modest_ui_actions_on_change_zoom),
1035 gtk_action_group_add_radio_actions (action_group,
1036 modest_msg_edit_priority_action_entries,
1037 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
1039 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
1041 gtk_action_group_add_radio_actions (action_group,
1042 modest_msg_edit_file_format_action_entries,
1043 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
1044 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
1045 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
1047 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1048 g_object_unref (action_group);
1050 /* Load the UI definition */
1051 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
1053 if (error != NULL) {
1054 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
1055 g_clear_error (&error);
1058 /* Add accelerators */
1059 gtk_window_add_accel_group (GTK_WINDOW (obj),
1060 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1063 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
1064 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1067 init_window (MODEST_MSG_EDIT_WINDOW(obj));
1069 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1071 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1073 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1074 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1076 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
1078 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
1079 if (account_pair != NULL)
1080 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
1082 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg);
1084 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1086 /* Set window icon */
1087 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
1089 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1090 g_object_unref (window_icon);
1093 /* Dim at start clipboard actions */
1094 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
1095 gtk_action_set_sensitive (action, FALSE);
1096 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
1097 gtk_action_set_sensitive (action, FALSE);
1098 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
1099 gtk_action_set_sensitive (action, FALSE);
1101 /* Update select all */
1102 update_select_all_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1103 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu");
1104 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (edit_menu_activated), obj);
1105 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu");
1106 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (view_menu_activated), obj);
1108 /* set initial state of cc and bcc */
1109 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
1110 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1111 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
1112 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
1113 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1114 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
1116 /* Setup the file format */
1117 conf = modest_runtime_get_conf ();
1118 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
1120 g_clear_error (&error);
1121 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
1123 file_format = (prefer_formatted) ?
1124 MODEST_FILE_FORMAT_FORMATTED_TEXT :
1125 MODEST_FILE_FORMAT_PLAIN_TEXT;
1126 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
1128 update_paste_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1129 priv->update_caption_visibility = TRUE;
1131 return (ModestWindow*) obj;
1135 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1137 GString **string_buffer = (GString **) user_data;
1139 *string_buffer = g_string_append (*string_buffer, buffer);
1145 * @result: A new string which should be freed with g_free().
1148 get_formatted_data (ModestMsgEditWindow *edit_window)
1150 ModestMsgEditWindowPrivate *priv;
1151 GString *string_buffer = g_string_new ("");
1153 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1155 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1157 return g_string_free (string_buffer, FALSE);
1162 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1165 const gchar *account_name;
1166 ModestMsgEditWindowPrivate *priv;
1168 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1170 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1172 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1173 g_return_val_if_fail (account_name, NULL);
1176 /* don't free these (except from) */
1177 data = g_slice_new0 (MsgData);
1178 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1180 data->account_name = g_strdup (account_name);
1181 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1182 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1183 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1184 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1185 if (priv->draft_msg) {
1186 data->draft_msg = g_object_ref (priv->draft_msg);
1188 data->draft_msg = NULL;
1191 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1193 gtk_text_buffer_get_bounds (buf, &b, &e);
1194 data->plain_body = g_strdup (gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE)); /* returns a copy */
1196 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1197 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1199 data->html_body = NULL;
1201 /* deep-copy the data */
1202 GList *cursor = priv->attachments;
1203 data->attachments = NULL;
1205 if (!(TNY_IS_MIME_PART(cursor->data))) {
1206 g_warning ("strange data in attachment list");
1207 cursor = g_list_next (cursor);
1210 data->attachments = g_list_append (data->attachments,
1211 g_object_ref (cursor->data));
1212 cursor = g_list_next (cursor);
1215 data->priority_flags = priv->priority_flags;
1222 unref_gobject (GObject *obj, gpointer data)
1224 if (!G_IS_OBJECT(obj))
1226 g_object_unref (obj);
1230 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1233 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1241 g_free (data->subject);
1242 g_free (data->plain_body);
1243 g_free (data->html_body);
1244 g_free (data->account_name);
1246 if (data->draft_msg != NULL) {
1247 g_object_unref (data->draft_msg);
1248 data->draft_msg = NULL;
1251 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1252 g_list_free (data->attachments);
1254 g_slice_free (MsgData, data);
1258 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1261 ModestMsgEditWindowPrivate *priv = NULL;
1262 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1264 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1266 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1268 return MODEST_MSG_EDIT_FORMAT_HTML;
1270 return MODEST_MSG_EDIT_FORMAT_TEXT;
1274 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1275 ModestMsgEditFormat format)
1277 ModestMsgEditWindowPrivate *priv;
1279 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1280 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1283 case MODEST_MSG_EDIT_FORMAT_HTML:
1284 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1286 case MODEST_MSG_EDIT_FORMAT_TEXT:
1287 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1290 g_return_if_reached ();
1294 ModestMsgEditFormatState *
1295 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1297 ModestMsgEditFormatState *format_state = NULL;
1298 ModestMsgEditWindowPrivate *priv;
1299 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1301 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1302 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1304 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1306 format_state = g_new0 (ModestMsgEditFormatState, 1);
1307 format_state->bold = buffer_format->bold&0x1;
1308 format_state->italics = buffer_format->italic&0x1;
1309 format_state->bullet = buffer_format->bullet&0x1;
1310 format_state->color = buffer_format->color;
1311 format_state->font_size = buffer_format->font_size;
1312 format_state->font_family = wp_get_font_name (buffer_format->font);
1313 format_state->justification = buffer_format->justification;
1314 g_free (buffer_format);
1316 return format_state;
1321 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1322 const ModestMsgEditFormatState *format_state)
1324 ModestMsgEditWindowPrivate *priv;
1325 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1326 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1327 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1328 g_return_if_fail (format_state != NULL);
1330 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1331 gtk_widget_grab_focus (priv->msg_body);
1332 buffer_format->bold = (format_state->bold != FALSE);
1333 buffer_format->italic = (format_state->italics != FALSE);
1334 buffer_format->color = format_state->color;
1335 buffer_format->font_size = format_state->font_size;
1336 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1337 buffer_format->justification = format_state->justification;
1338 buffer_format->bullet = format_state->bullet;
1340 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1342 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1343 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1344 buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
1345 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1346 buffer_format->cs.font = (buffer_format->font != current_format->font);
1347 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1348 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1350 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1351 if (buffer_format->cs.bold) {
1352 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1354 if (buffer_format->cs.italic) {
1355 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1357 if (buffer_format->cs.color) {
1358 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1360 if (buffer_format->cs.font_size) {
1361 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1363 if (buffer_format->cs.justification) {
1364 switch (buffer_format->justification) {
1365 case GTK_JUSTIFY_LEFT:
1366 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1368 case GTK_JUSTIFY_CENTER:
1369 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1371 case GTK_JUSTIFY_RIGHT:
1372 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1379 if (buffer_format->cs.font) {
1380 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1382 if (buffer_format->cs.bullet) {
1383 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((int)buffer_format->bullet));
1385 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1386 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1388 g_free (current_format);
1393 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1395 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1397 ModestWindowPrivate *parent_priv;
1398 ModestMsgEditWindowPrivate *priv;
1399 GtkWidget *new_size_menuitem;
1400 GtkWidget *new_font_menuitem;
1402 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1403 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1405 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1406 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1407 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1408 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1410 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1411 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1412 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1415 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1417 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1418 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1420 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1421 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1423 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1424 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1426 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1427 G_CALLBACK (modest_msg_edit_window_color_button_change),
1429 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1430 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1431 G_CALLBACK (modest_msg_edit_window_color_button_change),
1434 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1435 buffer_format->font_size))->data);
1436 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1440 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1441 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1442 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1444 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1445 G_CALLBACK (modest_msg_edit_window_size_change),
1447 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1448 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1449 G_CALLBACK (modest_msg_edit_window_size_change),
1453 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1454 buffer_format->font))->data);
1455 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1459 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1460 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1461 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1463 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1464 G_CALLBACK (modest_msg_edit_window_font_change),
1466 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1467 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1468 G_CALLBACK (modest_msg_edit_window_font_change),
1472 g_free (buffer_format);
1478 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1481 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1482 ModestMsgEditWindowPrivate *priv;
1483 GtkWidget *dialog = NULL;
1485 const GdkColor *new_color = NULL;
1487 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1488 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1490 #ifdef MODEST_HILDON_VERSION_0
1491 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1492 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1494 dialog = hildon_color_chooser_new ();
1495 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1496 #endif /*MODEST_HILDON_VERSION_0*/
1497 g_free (buffer_format);
1499 response = gtk_dialog_run (GTK_DIALOG (dialog));
1501 case GTK_RESPONSE_OK: {
1502 #ifdef MODEST_HILDON_VERSION_0
1503 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1506 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1508 #endif /*MODEST_HILDON_VERSION_0*/
1515 gtk_widget_destroy (dialog);
1517 if (new_color != NULL)
1518 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1523 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1526 ModestMsgEditWindowPrivate *priv;
1527 GtkWidget *dialog = NULL;
1529 GdkColor *old_color = NULL;
1530 const GdkColor *new_color = NULL;
1532 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1533 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1535 #ifdef MODEST_HILDON_VERSION_0
1536 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1537 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1539 dialog = hildon_color_chooser_new ();
1540 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1541 #endif /*MODEST_HILDON_VERSION_9*/
1543 response = gtk_dialog_run (GTK_DIALOG (dialog));
1545 case GTK_RESPONSE_OK: {
1546 #ifdef MODEST_HILDON_VERSION_0
1547 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1550 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1552 #endif /*MODEST_HILDON_VERSION_0*/
1558 gtk_widget_destroy (dialog);
1560 if (new_color != NULL)
1561 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1565 static TnyStream* create_stream_for_uri (const gchar* uri)
1570 TnyStream *result = NULL;
1572 GnomeVFSHandle *handle = NULL;
1573 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1574 if (test == GNOME_VFS_OK) {
1575 /* Create the tinymail stream: */
1576 /* Presumably tinymai will call gnome_vfs_close (handle) later. */
1577 result = TNY_STREAM (tny_vfs_stream_new (handle));
1584 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1587 ModestMsgEditWindowPrivate *priv;
1588 GtkWidget *dialog = NULL;
1590 GSList *uris = NULL;
1591 GSList *uri_node = NULL;
1593 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1595 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1596 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1597 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1599 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1601 response = gtk_dialog_run (GTK_DIALOG (dialog));
1603 case GTK_RESPONSE_OK:
1604 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1609 gtk_widget_destroy (dialog);
1611 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1613 GnomeVFSHandle *handle = NULL;
1614 GnomeVFSResult result;
1615 GtkTextIter position;
1616 GtkTextMark *insert_mark;
1618 uri = (const gchar *) uri_node->data;
1619 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1620 if (result == GNOME_VFS_OK) {
1622 GnomeVFSFileInfo info;
1623 gchar *filename, *basename, *escaped_filename;
1624 TnyMimePart *mime_part;
1626 const gchar *mime_type = NULL;
1627 GnomeVFSURI *vfs_uri;
1629 vfs_uri = gnome_vfs_uri_new (uri);
1631 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1632 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1633 g_free (escaped_filename);
1634 gnome_vfs_uri_unref (vfs_uri);
1636 if (gnome_vfs_get_file_info (uri, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
1637 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1639 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1641 mime_part = tny_platform_factory_new_mime_part
1642 (modest_runtime_get_platform_factory ());
1644 TnyStream *stream = create_stream_for_uri (uri);
1645 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1647 content_id = g_strdup_printf ("%d", priv->last_cid);
1648 tny_mime_part_set_content_id (mime_part, content_id);
1649 g_free (content_id);
1652 basename = g_path_get_basename (filename);
1653 tny_mime_part_set_filename (mime_part, basename);
1656 pixbuf = pixbuf_from_stream (stream, mime_type);
1658 if (pixbuf != NULL) {
1659 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1660 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1661 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1664 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1665 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1667 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1668 gtk_widget_show_all (priv->attachments_caption);
1669 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1679 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
1682 ModestMsgEditWindowPrivate *priv;
1683 GtkWidget *dialog = NULL;
1685 GSList *uris = NULL;
1688 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1690 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1691 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
1692 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1694 response = gtk_dialog_run (GTK_DIALOG (dialog));
1696 case GTK_RESPONSE_OK:
1697 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1702 gtk_widget_destroy (dialog);
1704 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1705 const gchar *uri = (const gchar *) uri_node->data;
1706 modest_msg_edit_window_attach_file_one (window, uri);
1708 g_slist_foreach (uris, (GFunc) g_free, NULL);
1709 g_slist_free (uris);
1713 modest_msg_edit_window_attach_file_one (
1714 ModestMsgEditWindow *window,
1717 g_return_if_fail (window);
1718 g_return_if_fail (uri);
1720 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1723 GnomeVFSHandle *handle = NULL;
1724 GnomeVFSResult result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1725 if (result == GNOME_VFS_OK) {
1726 TnyMimePart *mime_part;
1728 const gchar *mime_type = NULL;
1730 gchar *escaped_filename;
1733 GnomeVFSFileInfo info;
1734 GnomeVFSURI *vfs_uri;
1736 vfs_uri = gnome_vfs_uri_new (uri);
1739 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1740 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1741 g_free (escaped_filename);
1742 gnome_vfs_uri_unref (vfs_uri);
1744 if (gnome_vfs_get_file_info (uri,
1746 GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
1747 GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1749 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1750 mime_part = tny_platform_factory_new_mime_part
1751 (modest_runtime_get_platform_factory ());
1752 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1754 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1756 content_id = g_strdup_printf ("%d", priv->last_cid);
1757 tny_mime_part_set_content_id (mime_part, content_id);
1758 g_free (content_id);
1761 basename = g_path_get_basename (filename);
1762 tny_mime_part_set_filename (mime_part, basename);
1765 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1766 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1768 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1769 gtk_widget_show_all (priv->attachments_caption);
1770 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1776 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1779 ModestMsgEditWindowPrivate *priv;
1780 gboolean clean_list = FALSE;
1782 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1783 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1785 if (att_list == NULL) {
1786 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1790 if (att_list == NULL) {
1791 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1793 GtkWidget *confirmation_dialog = NULL;
1794 gboolean dialog_response;
1796 gchar *message = NULL;
1797 const gchar *filename = NULL;
1799 if (att_list->next == NULL) {
1800 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1804 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1805 att_list->next == NULL), filename);
1806 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1808 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1809 gtk_widget_destroy (confirmation_dialog);
1810 if (!dialog_response) {
1812 g_list_free (att_list);
1815 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1817 for (node = att_list; node != NULL; node = g_list_next (node)) {
1818 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1819 const gchar *att_id;
1820 priv->attachments = g_list_remove (priv->attachments, mime_part);
1822 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1824 if (priv->attachments == NULL)
1825 gtk_widget_hide (priv->attachments_caption);
1826 att_id = tny_mime_part_get_content_id (mime_part);
1828 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1830 g_object_unref (mime_part);
1831 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1836 g_list_free (att_list);
1840 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1843 ModestMsgEditWindowPrivate *priv;
1844 GdkColor *new_color;
1845 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1847 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1848 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1851 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1853 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1855 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1857 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1862 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1865 ModestMsgEditWindowPrivate *priv;
1866 gint new_size_index;
1867 ModestMsgEditWindow *window;
1870 window = MODEST_MSG_EDIT_WINDOW (userdata);
1871 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1872 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1874 if (gtk_check_menu_item_get_active (menu_item)) {
1876 WPTextBufferFormat format;
1878 memset (&format, 0, sizeof (format));
1879 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1881 label = gtk_bin_get_child (GTK_BIN (menu_item));
1883 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1884 format.cs.font_size = TRUE;
1885 format.cs.text_position = TRUE;
1886 format.cs.font = TRUE;
1887 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1888 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1890 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1891 (gpointer) wp_get_font_size_index (new_size_index, 12)))
1892 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1894 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1895 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1896 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1902 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1905 ModestMsgEditWindowPrivate *priv;
1906 gint new_font_index;
1907 ModestMsgEditWindow *window;
1910 window = MODEST_MSG_EDIT_WINDOW (userdata);
1911 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1912 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1914 if (gtk_check_menu_item_get_active (menu_item)) {
1917 label = gtk_bin_get_child (GTK_BIN (menu_item));
1919 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1921 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1922 (gpointer) new_font_index))
1923 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1925 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1926 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1927 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1933 modest_msg_edit_window_set_zoom (ModestWindow *window,
1936 ModestMsgEditWindowPrivate *priv;
1937 ModestWindowPrivate *parent_priv;
1938 GtkRadioAction *zoom_radio_action;
1940 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1942 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1943 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1944 priv->zoom_level = zoom;
1945 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom*DEFAULT_FONT_SCALE);
1947 /* Zoom level menu options should be updated with the current zoom level */
1948 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1949 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1950 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1951 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1952 /* FIXME: Not availible before Gtk 2.10 */
1954 gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
1959 modest_msg_edit_window_get_zoom (ModestWindow *window)
1961 ModestMsgEditWindowPrivate *priv;
1963 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1965 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1966 return priv->zoom_level;
1970 zoom_allowed (ModestMsgEditWindow *window)
1974 focus = gtk_window_get_focus (GTK_WINDOW (window));
1975 return (focus != NULL && WP_IS_TEXT_VIEW (focus));
1979 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1981 ModestWindowPrivate *parent_priv;
1982 GtkRadioAction *zoom_radio_action;
1983 GSList *group, *node;
1985 /* First we check if the text view is focused. If not, zooming is not allowed */
1986 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1987 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1991 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1992 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1993 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1995 group = gtk_radio_action_get_group (zoom_radio_action);
1997 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1998 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
2002 for (node = group; node != NULL; node = g_slist_next (node)) {
2003 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
2004 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
2012 modest_msg_edit_window_zoom_minus (ModestWindow *window)
2014 ModestWindowPrivate *parent_priv;
2015 GtkRadioAction *zoom_radio_action;
2016 GSList *group, *node;
2018 /* First we check if the text view is focused. If not, zooming is not allowed */
2019 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2020 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2024 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2025 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2026 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2028 group = gtk_radio_action_get_group (zoom_radio_action);
2030 for (node = group; node != NULL; node = g_slist_next (node)) {
2031 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
2032 if (node->next != NULL) {
2033 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
2036 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
2044 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2046 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2047 ModestWindowPrivate *parent_priv;
2048 ModestWindowMgr *mgr;
2049 gboolean is_fullscreen;
2050 GtkAction *fs_toggle_action;
2053 mgr = modest_runtime_get_window_mgr ();
2054 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2056 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2058 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2059 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2060 if (is_fullscreen != active)
2061 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2069 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
2071 ModestWindowPrivate *parent_priv;
2072 GtkAction *fs_toggle_action;
2075 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2077 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2078 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
2079 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
2083 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2086 ModestMsgEditWindowPrivate *priv = NULL;
2087 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2089 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2090 if (!priv->update_caption_visibility)
2093 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2095 gtk_widget_show (priv->cc_caption);
2097 gtk_widget_hide (priv->cc_caption);
2099 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2103 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2106 ModestMsgEditWindowPrivate *priv = NULL;
2107 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2109 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2110 if (!priv->update_caption_visibility)
2113 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2115 gtk_widget_show (priv->bcc_caption);
2117 gtk_widget_hide (priv->bcc_caption);
2119 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2123 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2124 ModestRecptEditor *editor)
2126 ModestMsgEditWindowPrivate *priv;
2128 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2129 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2130 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2132 if (editor == NULL) {
2133 GtkWidget *view_focus;
2134 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2136 /* This code should be kept in sync with ModestRecptEditor. The
2137 textview inside the recpt editor is the one that really gets the
2138 focus. As it's inside a scrolled window, and this one inside the
2139 hbox recpt editor inherits from, we'll need to go up in the
2140 hierarchy to know if the text view is part of the recpt editor
2141 or if it's a different text entry */
2143 if (gtk_widget_get_parent (view_focus)) {
2144 GtkWidget *first_parent;
2146 first_parent = gtk_widget_get_parent (view_focus);
2147 if (gtk_widget_get_parent (first_parent) &&
2148 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2149 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2154 editor = MODEST_RECPT_EDITOR (priv->to_field);
2158 modest_address_book_select_addresses (editor);
2163 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2165 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2167 modest_msg_edit_window_open_addressbook (window, NULL);
2171 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2172 gboolean show_toolbar)
2174 ModestWindowPrivate *parent_priv;
2176 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2177 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2179 /* FIXME: we can not just use the code of
2180 modest_msg_edit_window_setup_toolbar because it has a
2181 mixture of both initialization and creation code. */
2184 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2186 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2190 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2191 TnyHeaderFlags priority_flags)
2193 ModestMsgEditWindowPrivate *priv;
2194 ModestWindowPrivate *parent_priv;
2196 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2198 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2199 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2200 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2202 if (priv->priority_flags != priority_flags) {
2203 GtkAction *priority_action = NULL;
2205 priv->priority_flags = priority_flags;
2207 switch (priority_flags) {
2208 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2209 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2210 gtk_widget_show (priv->priority_icon);
2211 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2212 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2214 case TNY_HEADER_FLAG_LOW_PRIORITY:
2215 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2216 gtk_widget_show (priv->priority_icon);
2217 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2218 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2221 gtk_widget_hide (priv->priority_icon);
2222 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2223 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2226 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2227 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2232 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2235 ModestMsgEditWindowPrivate *priv;
2236 ModestWindowPrivate *parent_priv;
2237 gint current_format;
2239 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2241 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2242 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2244 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2245 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2247 if (current_format != file_format) {
2248 switch (file_format) {
2249 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2250 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2252 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2256 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2257 response = gtk_dialog_run (GTK_DIALOG (dialog));
2258 gtk_widget_destroy (dialog);
2259 if (response == GTK_RESPONSE_OK) {
2260 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2262 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2263 modest_maemo_toggle_action_set_active_block_notify (action, TRUE);
2268 update_dimmed (window);
2273 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2276 ModestMsgEditWindowPrivate *priv;
2277 WPTextBufferFormat oldfmt, fmt;
2278 gint old_position = 0;
2282 GdkColor *color = NULL;
2283 gboolean bold, bold_set, italic, italic_set;
2284 gboolean underline, underline_set;
2285 gboolean strikethrough, strikethrough_set;
2286 gboolean position_set;
2287 gboolean font_size_set, font_set, color_set;
2290 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2291 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2293 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2295 /* First we get the currently selected font information */
2296 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2297 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2299 switch (oldfmt.text_position) {
2300 case TEXT_POSITION_NORMAL:
2303 case TEXT_POSITION_SUPERSCRIPT:
2311 g_object_set (G_OBJECT (dialog),
2312 "bold", oldfmt.bold != FALSE,
2313 "bold-set", !oldfmt.cs.bold,
2314 "underline", oldfmt.underline != FALSE,
2315 "underline-set", !oldfmt.cs.underline,
2316 "italic", oldfmt.italic != FALSE,
2317 "italic-set", !oldfmt.cs.italic,
2318 "strikethrough", oldfmt.strikethrough != FALSE,
2319 "strikethrough-set", !oldfmt.cs.strikethrough,
2320 "color", &oldfmt.color,
2321 "color-set", !oldfmt.cs.color,
2322 "size", wp_font_size[oldfmt.font_size],
2323 "size-set", !oldfmt.cs.font_size,
2324 "position", old_position,
2325 "position-set", !oldfmt.cs.text_position,
2326 "family", wp_get_font_name (oldfmt.font),
2327 "family-set", !oldfmt.cs.font,
2330 gtk_widget_show_all (dialog);
2331 response = gtk_dialog_run (GTK_DIALOG (dialog));
2332 if (response == GTK_RESPONSE_OK) {
2334 g_object_get( dialog,
2336 "bold-set", &bold_set,
2337 "underline", &underline,
2338 "underline-set", &underline_set,
2340 "italic-set", &italic_set,
2341 "strikethrough", &strikethrough,
2342 "strikethrough-set", &strikethrough_set,
2344 "color-set", &color_set,
2346 "size-set", &font_size_set,
2347 "family", &font_name,
2348 "family-set", &font_set,
2349 "position", &position,
2350 "position-set", &position_set,
2355 if (response == GTK_RESPONSE_OK) {
2356 memset(&fmt, 0, sizeof(fmt));
2362 fmt.italic = italic;
2363 fmt.cs.italic = TRUE;
2365 if (underline_set) {
2366 fmt.underline = underline;
2367 fmt.cs.underline = TRUE;
2369 if (strikethrough_set) {
2370 fmt.strikethrough = strikethrough;
2371 fmt.cs.strikethrough = TRUE;
2376 ? TEXT_POSITION_NORMAL
2377 : ( ( position == 1 )
2378 ? TEXT_POSITION_SUPERSCRIPT
2379 : TEXT_POSITION_SUBSCRIPT );
2380 fmt.cs.text_position = TRUE;
2384 fmt.cs.color = TRUE;
2387 fmt.font = wp_get_font_index(font_name,
2392 if (font_size_set) {
2393 fmt.font_size = wp_get_font_size_index(
2394 font_size, DEFAULT_FONT_SIZE);
2395 fmt.cs.font_size = TRUE;
2397 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2399 gtk_widget_destroy (dialog);
2401 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2405 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2407 ModestMsgEditWindowPrivate *priv;
2409 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2410 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2412 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2414 update_dimmed (window);
2419 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2421 ModestMsgEditWindowPrivate *priv;
2423 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2424 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2426 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2428 update_dimmed (window);
2433 update_dimmed (ModestMsgEditWindow *window)
2435 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2436 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2440 gboolean editor_focused;
2442 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2443 editor_focused = gtk_widget_is_focus (priv->msg_body);
2445 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2446 gtk_action_set_sensitive (action, rich_text && editor_focused);
2447 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2448 gtk_action_set_sensitive (action, rich_text && editor_focused);
2449 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2450 gtk_action_set_sensitive (action, rich_text && editor_focused);
2451 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2452 gtk_action_set_sensitive (action, rich_text && editor_focused);
2453 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2454 gtk_action_set_sensitive (action, rich_text && editor_focused);
2455 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2456 gtk_action_set_sensitive (action, rich_text && editor_focused);
2457 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2458 gtk_action_set_sensitive (action, rich_text && editor_focused);
2459 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2460 gtk_action_set_sensitive (action, rich_text && editor_focused);
2461 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2462 gtk_action_set_sensitive (action, rich_text && editor_focused);
2463 widget = priv->font_color_button;
2464 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2465 widget = priv->font_size_toolitem;
2466 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2467 widget = priv->font_face_toolitem;
2468 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2472 setup_insensitive_handlers (ModestMsgEditWindow *window)
2474 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2475 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2478 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2479 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2480 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2481 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2482 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2483 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2484 widget = priv->font_color_button;
2485 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2486 widget = priv->font_size_toolitem;
2487 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2488 widget = priv->font_face_toolitem;
2489 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2494 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2496 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2499 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2500 gtk_action_set_sensitive (action, can_undo);
2504 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2506 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2509 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/RedoMenu");
2510 gtk_action_set_sensitive (action, can_redo);
2514 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2517 GtkTextIter match_start, match_end;
2519 if (image_id == NULL)
2522 gtk_text_buffer_get_start_iter (buffer, &iter);
2524 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2525 GSList *tags = gtk_text_iter_get_tags (&match_start);
2527 for (node = tags; node != NULL; node = g_slist_next (node)) {
2528 GtkTextTag *tag = (GtkTextTag *) node->data;
2529 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2530 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2531 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2533 offset = gtk_text_iter_get_offset (&match_start);
2534 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2535 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2539 gtk_text_iter_forward_char (&iter);
2544 msg_body_focus (GtkWidget *focus,
2545 GdkEventFocus *event,
2549 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2554 recpt_field_changed (GtkTextBuffer *buffer,
2555 ModestMsgEditWindow *editor)
2557 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2558 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2559 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2560 gboolean dim = FALSE;
2563 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2564 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2565 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2567 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2568 gtk_text_buffer_get_char_count (cc_buffer) +
2569 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2571 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2572 gtk_action_set_sensitive (action, !dim);
2573 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2574 gtk_action_set_sensitive (action, !dim);
2578 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2580 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2584 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2586 gboolean rich_text, editor_focused;
2588 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2589 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2590 editor_focused = gtk_widget_is_focus (priv->msg_body);
2593 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2594 else if (!editor_focused)
2595 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2599 reset_modified (ModestMsgEditWindow *editor)
2601 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2602 GtkTextBuffer *buffer;
2604 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2605 gtk_text_buffer_set_modified (buffer, FALSE);
2606 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2607 gtk_text_buffer_set_modified (buffer, FALSE);
2608 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2609 gtk_text_buffer_set_modified (buffer, FALSE);
2610 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2614 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2616 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2617 GtkTextBuffer *buffer;
2619 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2620 if (gtk_text_buffer_get_modified (buffer))
2622 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2623 if (gtk_text_buffer_get_modified (buffer))
2625 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2626 if (gtk_text_buffer_get_modified (buffer))
2628 if (gtk_text_buffer_get_modified (priv->text_buffer))
2635 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
2637 ModestMsgEditWindowPrivate *priv = NULL;
2639 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2640 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2642 /* check if there's no recipient added */
2643 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2644 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2645 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2646 /* no recipient contents, then select contacts */
2647 modest_msg_edit_window_open_addressbook (window, NULL);
2651 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook))
2653 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook))
2655 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook))
2658 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2665 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2666 ModestMsgEditWindow *window)
2668 modest_msg_edit_window_offer_attach_file (window);
2672 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2674 ModestMsgEditWindow *window)
2676 ModestWindowPrivate *parent_priv;
2677 ModestMsgEditWindowPrivate *priv;
2679 gboolean has_selection;
2681 GList *selected_attachments = NULL;
2682 gint n_att_selected = 0;
2684 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2685 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2687 if (!GTK_WIDGET_VISIBLE (window))
2689 has_selection = gtk_clipboard_wait_for_targets (clipboard, NULL, NULL);
2690 focused = gtk_window_get_focus (GTK_WINDOW (window));
2692 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2693 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2694 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2695 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2697 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2698 n_att_selected = g_list_length (selected_attachments);
2699 g_list_free (selected_attachments);
2701 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2702 gtk_action_set_sensitive (action, n_att_selected == 1);
2704 update_paste_dimming (window);
2708 update_window_title (ModestMsgEditWindow *window)
2710 ModestMsgEditWindowPrivate *priv = NULL;
2711 const gchar *subject;
2713 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2714 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2715 if (subject == NULL || subject[0] == '\0')
2716 subject = _("mail_va_new_email");
2718 gtk_window_set_title (GTK_WINDOW (window), subject);
2723 subject_field_changed (GtkEditable *editable,
2724 ModestMsgEditWindow *window)
2726 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2727 update_window_title (window);
2728 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2732 message_is_empty (ModestMsgEditWindow *window)
2734 ModestMsgEditWindowPrivate *priv = NULL;
2736 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2737 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2739 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
2740 * so we can ignore markup.
2742 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
2745 count = gtk_text_buffer_get_char_count (buf);
2751 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2754 ModestMsgEditWindowPrivate *priv = NULL;
2756 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2757 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2759 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2762 gtk_widget_show_all (priv->find_toolbar);
2763 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2765 gtk_widget_hide_all (priv->find_toolbar);
2766 gtk_widget_grab_focus (priv->msg_body);
2772 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2774 GtkTextIter *match_start,
2775 GtkTextIter *match_end)
2777 GtkTextIter end_iter;
2778 gchar *str_casefold;
2781 gchar *range_casefold;
2784 gboolean result = FALSE;
2791 gtk_text_iter_forward_to_end (&end_iter);
2793 str_casefold = g_utf8_casefold (str, -1);
2794 str_chars_n = strlen (str);
2796 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2797 range_casefold = g_utf8_casefold (range_text, -1);
2798 range_chars_n = strlen (range_casefold);
2800 if (range_chars_n < str_chars_n) {
2801 g_free (str_casefold);
2802 g_free (range_text);
2803 g_free (range_casefold);
2807 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2808 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2809 if (!g_utf8_collate (range_subtext, str_casefold)) {
2810 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2812 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2813 match_start, match_end, NULL);
2814 g_free (found_text);
2816 g_free (range_subtext);
2820 g_free (str_casefold);
2821 g_free (range_text);
2822 g_free (range_casefold);
2829 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2830 ModestMsgEditWindow *window)
2832 gchar *current_search = NULL;
2833 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2835 GtkTextIter selection_start, selection_end;
2836 GtkTextIter match_start, match_end;
2837 gboolean continue_search = FALSE;
2839 if (message_is_empty (window)) {
2840 g_free (priv->last_search);
2841 priv->last_search = NULL;
2842 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
2846 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2847 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2848 g_free (current_search);
2849 g_free (priv->last_search);
2850 priv->last_search = NULL;
2851 /* Information banner about empty search */
2852 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2856 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2857 continue_search = TRUE;
2859 g_free (priv->last_search);
2860 priv->last_search = g_strdup (current_search);
2863 if (continue_search) {
2864 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2865 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2866 &match_start, &match_end);
2868 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2870 GtkTextIter buffer_start;
2871 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2872 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2873 &match_start, &match_end);
2875 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2878 /* Mark as selected the string found in search */
2880 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2881 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2883 g_free (priv->last_search);
2884 priv->last_search = NULL;
2886 g_free (current_search);
2890 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2891 ModestMsgEditWindow *window)
2893 GtkToggleAction *toggle;
2894 ModestWindowPrivate *parent_priv;
2895 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2897 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2898 gtk_toggle_action_set_active (toggle, FALSE);
2903 update_paste_dimming (ModestMsgEditWindow *window)
2905 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2906 GtkAction *action = NULL;
2907 GtkClipboard *clipboard = NULL;
2908 ModestEmailClipboard *e_clipboard;
2912 focused = gtk_window_get_focus (GTK_WINDOW (window));
2914 e_clipboard = modest_runtime_get_email_clipboard ();
2915 if (!modest_email_clipboard_cleared (e_clipboard)) {
2918 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2919 active = gtk_clipboard_wait_is_text_available (clipboard);
2923 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2927 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2928 gtk_action_set_sensitive (action, active);
2933 update_select_all_dimming (ModestMsgEditWindow *window)
2936 gboolean dimmed = FALSE;
2938 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2940 focused = gtk_window_get_focus (GTK_WINDOW (window));
2941 if (GTK_IS_ENTRY (focused)) {
2942 const gchar *current_text;
2943 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
2944 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
2945 } else if (GTK_IS_TEXT_VIEW (focused)) {
2946 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
2947 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
2948 } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
2951 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
2952 gtk_action_set_sensitive (action, !dimmed);
2956 update_zoom_dimming (ModestMsgEditWindow *window)
2959 gboolean dimmed = FALSE;
2961 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2963 focused = gtk_window_get_focus (GTK_WINDOW (window));
2964 dimmed = ! WP_IS_TEXT_VIEW (focused);
2965 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2966 gtk_action_set_sensitive (action, !dimmed);
2970 edit_menu_activated (GtkAction *action,
2973 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2975 update_select_all_dimming (window);
2976 update_paste_dimming (window);
2979 view_menu_activated (GtkAction *action,
2982 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2984 update_zoom_dimming (window);
2988 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
2990 ModestMsgEditWindowPrivate *priv;
2992 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
2997 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3000 ModestMsgEditWindowPrivate *priv;
3002 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3008 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3011 ModestMsgEditWindowPrivate *priv;
3012 TnyHeader *header = NULL;
3014 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3015 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3017 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3018 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3020 if (priv->draft_msg != NULL) {
3021 header = tny_msg_get_header (priv->draft_msg);
3022 if (TNY_IS_HEADER (header)) {
3023 modest_window_mgr_unregister_header (mgr, header);
3025 g_object_unref (priv->draft_msg);
3028 if (draft != NULL) {
3029 g_object_ref (draft);
3030 header = tny_msg_get_header (draft);
3031 if (TNY_IS_HEADER (header))
3032 modest_window_mgr_register_header (mgr, header);
3035 priv->draft_msg = draft;
3039 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3040 GtkTextIter *start, GtkTextIter *end,
3043 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3044 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3047 if (tag == NULL+13) return;
3048 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3049 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3050 replace_with_attachments (window, priv->attachments);
3055 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3058 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3060 g_return_if_fail (TNY_IS_MIME_PART (part));
3061 priv->attachments = g_list_prepend (priv->attachments, part);
3062 g_object_ref (part);
3063 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part);
3064 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3065 gtk_widget_show_all (priv->attachments_caption);
3066 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);