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"
65 #include "modest-msg-edit-window-ui-dimming.h"
67 #include "modest-hildon-includes.h"
68 #ifdef MODEST_HAVE_HILDON0_WIDGETS
69 #include <hildon-widgets/hildon-color-chooser.h>
71 #include "widgets/modest-msg-edit-window-ui.h"
72 #ifdef MODEST_HAVE_HILDON0_WIDGETS
73 #include <libgnomevfs/gnome-vfs-mime-utils.h>
75 #include <libgnomevfs/gnome-vfs-mime.h>
77 #include "modest-maemo-utils.h"
80 #define DEFAULT_FONT_SIZE 3
81 #define DEFAULT_FONT 2
82 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
83 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
84 #define DEFAULT_MAIN_VBOX_SPACING 6
85 #define SUBJECT_MAX_LENGTH 1000
86 #define IMAGE_MAX_WIDTH 560
87 #define DEFAULT_FONT_SCALE 1.5
89 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
90 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
91 static void modest_msg_edit_window_finalize (GObject *obj);
93 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
94 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
95 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
96 static void reset_modified (ModestMsgEditWindow *editor);
98 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
99 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
100 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
101 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
102 GtkTextIter *start, GtkTextIter *end,
104 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
105 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
106 static void subject_field_insert_text (GtkEditable *editable,
108 gint new_text_length,
110 ModestMsgEditWindow *window);
111 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
113 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
115 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
117 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
118 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
119 GdkEventWindowState *event,
121 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
122 ModestRecptEditor *editor);
123 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
124 ModestMsgEditWindow *window);
126 /* ModestWindow methods implementation */
127 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
128 static void modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom);
129 static gdouble modest_msg_edit_window_get_zoom (ModestWindow *window);
130 static gboolean modest_msg_edit_window_zoom_minus (ModestWindow *window);
131 static gboolean modest_msg_edit_window_zoom_plus (ModestWindow *window);
132 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
133 gboolean show_toolbar);
134 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
136 ModestMsgEditWindow *window);
137 static void subject_field_move_cursor (GtkEntry *entry,
138 GtkMovementStep step,
142 static void update_window_title (ModestMsgEditWindow *window);
145 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
146 ModestMsgEditWindow *window);
147 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
148 ModestMsgEditWindow *window);
149 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
151 GtkTextIter *match_start,
152 GtkTextIter *match_end);
154 static void DEBUG_BUFFER (WPTextBuffer *buffer)
159 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
160 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
161 while (!gtk_text_iter_is_end (&iter)) {
162 GString *output = g_string_new ("");
163 GSList *toggled_tags;
166 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
167 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
168 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
169 GtkTextTag *tag = (GtkTextTag *) node->data;
171 g_object_get (G_OBJECT (tag), "name", &name, NULL);
172 output = g_string_append (output, name);
173 g_string_append (output, " ");
175 output = g_string_append (output, "] OPENED [ ");
176 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
177 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
178 GtkTextTag *tag = (GtkTextTag *) node->data;
180 g_object_get (G_OBJECT (tag), "name", &name, NULL);
181 output = g_string_append (output, name);
182 g_string_append (output, " ");
184 output = g_string_append (output, "]\n");
185 g_message ("%s", output->str);
186 g_string_free (output, TRUE);
187 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
189 g_message ("END BUFFER");
194 /* static gboolean */
195 /* on_key_pressed (GtkWidget *self, */
196 /* GdkEventKey *event, */
197 /* gpointer user_data); */
199 /* list my signals */
206 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
207 struct _ModestMsgEditWindowPrivate {
209 GtkWidget *header_box;
211 ModestPairList *from_field_protos;
212 GtkWidget *from_field;
216 GtkWidget *bcc_field;
217 GtkWidget *subject_field;
218 GtkWidget *attachments_view;
219 GtkWidget *priority_icon;
220 GtkWidget *add_attachment_button;
222 GtkWidget *cc_caption;
223 GtkWidget *bcc_caption;
224 gboolean update_caption_visibility;
225 GtkWidget *attachments_caption;
227 GtkTextBuffer *text_buffer;
229 GtkWidget *font_size_toolitem;
230 GtkWidget *font_face_toolitem;
231 GtkWidget *font_color_button;
232 GSList *font_items_group;
233 GtkWidget *font_tool_button_label;
234 GSList *size_items_group;
235 GtkWidget *size_tool_button_label;
237 GtkWidget *find_toolbar;
241 GtkWidget *scroll_area;
242 gint last_vadj_upper;
247 TnyHeaderFlags priority_flags;
251 gboolean can_undo, can_redo;
252 gulong clipboard_change_handler_id;
253 gulong default_clipboard_change_handler_id;
262 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
263 MODEST_TYPE_MSG_EDIT_WINDOW, \
264 ModestMsgEditWindowPrivate))
266 static GtkWindowClass *parent_class = NULL;
268 /* uncomment the following if you have defined any signals */
269 /* static guint signals[LAST_SIGNAL] = {0}; */
272 modest_msg_edit_window_get_type (void)
274 static GType my_type = 0;
276 static const GTypeInfo my_info = {
277 sizeof(ModestMsgEditWindowClass),
278 NULL, /* base init */
279 NULL, /* base finalize */
280 (GClassInitFunc) modest_msg_edit_window_class_init,
281 NULL, /* class finalize */
282 NULL, /* class data */
283 sizeof(ModestMsgEditWindow),
285 (GInstanceInitFunc) modest_msg_edit_window_init,
288 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
289 "ModestMsgEditWindow",
292 wp_text_buffer_library_init ();
298 save_state (ModestWindow *self)
300 modest_widget_memory_save (modest_runtime_get_conf(),
301 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
306 restore_settings (ModestMsgEditWindow *self)
308 modest_widget_memory_restore (modest_runtime_get_conf(),
309 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
314 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
316 GObjectClass *gobject_class;
317 ModestWindowClass *modest_window_class;
318 gobject_class = (GObjectClass*) klass;
319 modest_window_class = (ModestWindowClass*) klass;
321 parent_class = g_type_class_peek_parent (klass);
322 gobject_class->finalize = modest_msg_edit_window_finalize;
324 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
325 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
326 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
327 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
328 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
329 modest_window_class->save_state_func = save_state;
330 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
332 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
336 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
338 ModestMsgEditWindowPrivate *priv;
339 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
341 priv->msg_body = NULL;
342 priv->from_field = NULL;
343 priv->to_field = NULL;
344 priv->cc_field = NULL;
345 priv->bcc_field = NULL;
346 priv->subject_field = NULL;
347 priv->attachments = NULL;
349 priv->zoom_level = 1.0;
351 priv->cc_caption = NULL;
352 priv->bcc_caption = NULL;
353 priv->update_caption_visibility = FALSE;
355 priv->priority_flags = 0;
357 priv->find_toolbar = NULL;
358 priv->last_search = NULL;
360 priv->draft_msg = NULL;
361 priv->outbox_msg = NULL;
362 priv->msg_uid = NULL;
364 priv->can_undo = FALSE;
365 priv->can_redo = FALSE;
366 priv->clipboard_change_handler_id = 0;
367 priv->default_clipboard_change_handler_id = 0;
370 priv->last_vadj_upper = 0;
374 /* FIXME: this is a dup from the one in gtk/ */
377 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
379 static ModestPairList*
380 get_transports (void)
382 GSList *transports = NULL;
384 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
385 GSList *accounts = modest_account_mgr_account_names (account_mgr,
386 TRUE /* only enabled accounts. */);
388 GSList *cursor = accounts;
390 gchar *account_name = cursor->data;
391 gchar *from_string = NULL;
393 from_string = modest_account_mgr_get_from_string (account_mgr,
397 if (from_string && account_name) {
398 gchar *name = account_name;
399 ModestPair *pair = modest_pair_new ((gpointer) name,
400 (gpointer) from_string , TRUE);
401 transports = g_slist_prepend (transports, pair);
404 cursor = cursor->next;
406 g_slist_free (accounts); /* only free the accounts, not the elements,
407 * because they are used in the pairlist */
411 void vadj_changed (GtkAdjustment *adj,
412 ModestMsgEditWindow *window)
414 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
416 GdkRectangle rectangle, cursor_rectangle;
417 GtkTextIter position;
421 /* We detect if cursor is visible using the full height, not only the center. This
423 gtk_text_view_get_visible_rect (GTK_TEXT_VIEW (priv->msg_body), &rectangle);
424 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer),
426 gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer)));
427 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &position, &cursor_rectangle);
429 cursor_bottom = (cursor_rectangle.y + cursor_rectangle.height);
430 visible = (cursor_rectangle.y >= rectangle.y) && (cursor_bottom < (rectangle.y + rectangle.height));
432 if (gtk_widget_is_focus (priv->msg_body) &&
434 if (priv->last_vadj_upper != adj->upper) {
437 insert = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
438 gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (priv->msg_body),
439 insert, 0.1, FALSE, 0.0, 0.0);
442 priv->last_vadj_upper = adj->upper;
447 init_window (ModestMsgEditWindow *obj)
449 GtkWidget *from_caption, *to_caption, *subject_caption;
450 GtkWidget *main_vbox;
451 ModestMsgEditWindowPrivate *priv;
453 GtkSizeGroup *size_group;
455 GtkWidget *subject_box;
456 GtkWidget *attachment_icon;
457 GtkWidget *window_box;
458 #if (GTK_MINOR_VERSION >= 10)
459 GdkAtom deserialize_type;
461 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
463 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
465 /* Note: This ModestPairList* must exist for as long as the combo
466 * that uses it, because the ModestComboBox uses the ID opaquely,
467 * so it can't know how to manage its memory. */
468 priv->from_field_protos = get_transports ();
470 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
472 priv->to_field = modest_recpt_editor_new ();
473 priv->cc_field = modest_recpt_editor_new ();
474 priv->bcc_field = modest_recpt_editor_new ();
475 subject_box = gtk_hbox_new (FALSE, 0);
476 priv->priority_icon = gtk_image_new ();
477 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
478 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
479 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
480 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
481 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
482 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
483 priv->add_attachment_button = gtk_button_new ();
484 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
485 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
486 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
487 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
488 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
489 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
490 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
491 priv->attachments_view = modest_attachments_view_new (NULL);
493 priv->header_box = gtk_vbox_new (FALSE, 0);
495 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
496 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
497 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
498 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
499 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
500 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
501 g_object_unref (size_group);
503 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
504 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
505 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
506 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
507 gtk_size_group_add_widget (size_group, priv->subject_field);
508 gtk_size_group_add_widget (size_group, priv->attachments_view);
509 g_object_unref (size_group);
511 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
512 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
513 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
514 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
515 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
516 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
517 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
520 priv->msg_body = wp_text_view_new ();
521 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
522 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
523 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
524 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
525 #if (GTK_MINOR_VERSION >= 10)
526 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
527 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
529 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
530 deserialize_type, TRUE);
532 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
534 priv->find_toolbar = hildon_find_toolbar_new (NULL);
535 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
537 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
539 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
540 G_CALLBACK (text_buffer_refresh_attributes), obj);
541 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
542 G_CALLBACK (text_buffer_can_undo), obj);
543 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
544 G_CALLBACK (text_buffer_can_redo), obj);
545 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
546 G_CALLBACK (body_changed), obj);
547 g_signal_connect (G_OBJECT (obj), "window-state-event",
548 G_CALLBACK (modest_msg_edit_window_window_state_event),
550 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
551 G_CALLBACK (text_buffer_apply_tag), obj);
552 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
553 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
554 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
555 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
556 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
557 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
559 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
560 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
562 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
563 G_CALLBACK (msg_body_focus), obj);
564 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
565 G_CALLBACK (msg_body_focus), obj);
566 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
567 "changed", G_CALLBACK (recpt_field_changed), obj);
568 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
569 "changed", G_CALLBACK (recpt_field_changed), obj);
570 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
571 "changed", G_CALLBACK (recpt_field_changed), obj);
572 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
573 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
574 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
576 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
577 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
579 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
580 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
581 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
582 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
584 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
586 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
587 frame = gtk_frame_new (NULL);
588 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
590 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
591 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
592 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
594 G_CALLBACK (vadj_changed),
596 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
598 window_box = gtk_vbox_new (FALSE, 0);
599 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
600 gtk_container_add (GTK_CONTAINER(obj), window_box);
601 priv->scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
602 gtk_container_add (GTK_CONTAINER (frame), priv->scroll_area);
604 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
605 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
606 priv->default_clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
607 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
612 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
614 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
616 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
617 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
618 priv->clipboard_change_handler_id))
619 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
620 priv->clipboard_change_handler_id);
621 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
622 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
623 priv->default_clipboard_change_handler_id))
624 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
625 priv->default_clipboard_change_handler_id);
629 modest_msg_edit_window_finalize (GObject *obj)
631 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
633 /* Sanity check: shouldn't be needed, the window mgr should
634 call this function before */
635 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
637 if (priv->draft_msg != NULL) {
638 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
639 if (TNY_IS_HEADER (header)) {
640 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
641 modest_window_mgr_unregister_header (mgr, header);
643 g_object_unref (priv->draft_msg);
644 priv->draft_msg = NULL;
646 if (priv->outbox_msg != NULL) {
647 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
648 if (TNY_IS_HEADER (header)) {
649 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
650 modest_window_mgr_unregister_header (mgr, header);
652 g_object_unref (priv->outbox_msg);
653 priv->outbox_msg = NULL;
655 if (priv->msg_uid != NULL) {
656 g_free (priv->msg_uid);
657 priv->msg_uid = NULL;
660 /* This had to stay alive for as long as the combobox that used it: */
661 modest_pair_list_free (priv->from_field_protos);
663 G_OBJECT_CLASS(parent_class)->finalize (obj);
667 menubar_to_menu (GtkUIManager *ui_manager)
669 GtkWidget *main_menu;
673 /* Create new main menu */
674 main_menu = gtk_menu_new();
676 /* Get the menubar from the UI manager */
677 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
679 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
683 menu = GTK_WIDGET (iter->data);
684 gtk_widget_reparent(menu, main_menu);
686 iter = g_list_next (iter);
692 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type)
694 GdkPixbufLoader *loader;
697 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
702 tny_stream_reset (TNY_STREAM (stream));
703 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
704 unsigned char read_buffer[128];
706 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
707 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
711 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
712 g_object_ref (pixbuf);
713 gdk_pixbuf_loader_close (loader, NULL);
714 g_object_unref (loader);
716 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
717 GdkPixbuf *new_pixbuf;
719 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
720 gdk_pixbuf_get_width (pixbuf);
721 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
722 g_object_unref (pixbuf);
730 replace_with_attachments (ModestMsgEditWindow *self, GList *attachments)
732 ModestMsgEditWindowPrivate *priv;
735 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
737 for (node = attachments; node != NULL; node = g_list_next (node)) {
738 TnyMimePart *part = (TnyMimePart *) node->data;
739 const gchar *cid = tny_mime_part_get_content_id (part);
740 const gchar *mime_type = tny_mime_part_get_content_type (part);
741 if ((cid != NULL)&&(mime_type != NULL)) {
742 TnyStream *stream = tny_mime_part_get_stream (part);
743 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type);
744 g_object_unref (stream);
746 if (pixbuf != NULL) {
747 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
748 g_object_unref (pixbuf);
755 update_last_cid (ModestMsgEditWindow *self, GList *attachments)
758 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
760 for (node = attachments; node != NULL; node = g_list_next (node)) {
761 TnyMimePart *part = (TnyMimePart *) node->data;
762 const gchar *cid = tny_mime_part_get_content_id (part);
764 char *invalid = NULL;
765 gint int_cid = strtol (cid, &invalid, 10);
766 if ((invalid != NULL) && (*invalid == '\0') && (int_cid > priv->last_cid)) {
767 priv->last_cid = int_cid;
775 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
778 const gchar *to, *cc, *bcc, *subject;
780 ModestMsgEditWindowPrivate *priv;
782 TnyHeaderFlags priority_flags;
783 TnyFolder *msg_folder;
784 gboolean is_html = FALSE;
786 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
787 g_return_if_fail (TNY_IS_MSG (msg));
789 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
791 header = tny_msg_get_header (msg);
792 to = tny_header_get_to (header);
793 cc = tny_header_get_cc (header);
794 bcc = tny_header_get_bcc (header);
795 subject = tny_header_get_subject (header);
796 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
799 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
801 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
802 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
803 gtk_widget_show (priv->cc_caption);
804 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
805 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
806 gtk_widget_hide (priv->cc_caption);
809 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
810 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
811 gtk_widget_show (priv->bcc_caption);
812 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
813 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
814 gtk_widget_hide (priv->bcc_caption);
817 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
818 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
821 update_window_title (self);
823 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
824 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
826 if ((body == NULL)||(body[0] == '\0')) {
828 body = modest_text_utils_convert_to_html ("");
831 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
832 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
835 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
838 /* Add attachments to the view */
839 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
840 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
841 if (priv->attachments == NULL) {
842 gtk_widget_hide (priv->attachments_caption);
844 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
845 gtk_widget_show_all (priv->attachments_caption);
846 replace_with_attachments (self, priv->attachments);
848 update_last_cid (self, priv->attachments);
850 if (preserve_is_rich && !is_html) {
851 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
852 /* Get the default format required from configuration */
853 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
854 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
857 /* Set the default focus depending on having already a To: field or not */
858 if ((!to)||(*to == '\0')) {
859 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
861 gtk_widget_grab_focus (priv->msg_body);
864 /* TODO: lower priority, select in the From: combo to the
865 value that comes from msg <- not sure, should it be
868 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
870 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
871 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
873 reset_modified (self);
875 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
876 text_buffer_can_undo (priv->text_buffer, FALSE, self);
877 text_buffer_can_redo (priv->text_buffer, FALSE, self);
880 g_free (priv->msg_uid);
881 priv->msg_uid = NULL;
884 /* we should set a reference to the incoming message if it is a draft */
885 msg_folder = tny_msg_get_folder (msg);
887 if (modest_tny_folder_is_local_folder (msg_folder)) {
888 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
889 if (type == TNY_FOLDER_TYPE_DRAFTS)
890 priv->draft_msg = g_object_ref(msg);
891 if (type == TNY_FOLDER_TYPE_OUTBOX)
892 priv->outbox_msg = g_object_ref(msg);
893 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
895 g_object_unref (msg_folder);
900 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
903 GList *item_children, *node;
904 GtkWidget *bin_child;
906 bin_child = gtk_bin_get_child (GTK_BIN(item));
908 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
910 for (node = item_children; node != NULL; node = g_list_next (node)) {
911 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
912 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
915 g_list_free (item_children);
919 menu_tool_button_dont_expand (GtkMenuToolButton *item)
922 GList *item_children, *node;
924 box = gtk_bin_get_child (GTK_BIN (item));
925 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
926 item_children = gtk_container_get_children (GTK_CONTAINER (box));
928 for (node = item_children; node != NULL; node = g_list_next (node)) {
929 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
930 if (GTK_IS_TOGGLE_BUTTON (node->data))
931 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
932 else if (GTK_IS_BUTTON (node->data))
933 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
935 g_list_free (item_children);
940 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
942 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
943 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
944 GtkWidget *placeholder;
945 GtkWidget *tool_item;
950 GtkWidget *sizes_menu;
951 GtkWidget *fonts_menu;
952 GSList *radio_group = NULL;
957 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
958 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
960 /* Font color placeholder */
961 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
962 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
965 tool_item = GTK_WIDGET (gtk_tool_item_new ());
966 priv->font_color_button = hildon_color_button_new ();
967 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
968 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
969 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
970 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
971 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
972 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
973 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
975 G_CALLBACK (modest_msg_edit_window_color_button_change),
978 /* Font size and face placeholder */
979 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
980 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
982 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
983 priv->size_tool_button_label = gtk_label_new (NULL);
984 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
985 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
986 size_text,"</span>", NULL);
987 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
989 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
990 sizes_menu = gtk_menu_new ();
991 priv->size_items_group = NULL;
993 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
994 GtkWidget *size_menu_item;
996 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
997 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
998 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
999 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1000 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1001 gtk_widget_show (size_menu_item);
1003 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1007 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1008 GtkWidget *item = (GtkWidget *) node->data;
1009 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1013 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1014 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1015 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1016 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1017 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1018 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1019 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1020 priv->font_size_toolitem = tool_item;
1023 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1024 priv->font_tool_button_label = gtk_label_new (NULL);
1025 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1026 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1028 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1029 fonts_menu = gtk_menu_new ();
1030 priv->font_items_group = NULL;
1032 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1033 GtkWidget *font_menu_item;
1034 GtkWidget *child_label;
1036 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1037 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1038 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1039 wp_get_font_name (font_index), "</span>", NULL);
1040 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1043 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1044 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1045 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1046 gtk_widget_show (font_menu_item);
1048 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1051 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1052 GtkWidget *item = (GtkWidget *) node->data;
1053 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1056 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1057 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1058 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1059 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1060 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1061 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1062 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1063 priv->font_face_toolitem = tool_item;
1065 /* Set expand and homogeneous for remaining items */
1066 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1067 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1068 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1069 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1070 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1071 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1072 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1073 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1074 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1076 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1077 will not show the tool items added to the placeholders) */
1078 gtk_widget_show_all (parent_priv->toolbar);
1080 /* Set the no show all *after* showing all items. We do not
1081 want the toolbar to be shown with a show all because it
1082 could go agains the gconf setting regarding showing or not
1083 the toolbar of the editor window */
1084 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1090 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1093 ModestWindowPrivate *parent_priv;
1094 ModestMsgEditWindowPrivate *priv;
1095 GtkActionGroup *action_group;
1096 GError *error = NULL;
1097 GdkPixbuf *window_icon = NULL;
1100 ModestPair *account_pair = NULL;
1101 ModestDimmingRulesGroup *menu_rules_group = NULL;
1102 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1103 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1105 g_return_val_if_fail (msg, NULL);
1106 g_return_val_if_fail (account_name, NULL);
1108 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
1110 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1111 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1113 parent_priv->ui_manager = gtk_ui_manager_new();
1114 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
1115 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1117 /* Add common actions */
1118 gtk_action_group_add_actions (action_group,
1119 modest_msg_edit_action_entries,
1120 G_N_ELEMENTS (modest_msg_edit_action_entries),
1122 gtk_action_group_add_toggle_actions (action_group,
1123 modest_msg_edit_toggle_action_entries,
1124 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
1126 gtk_action_group_add_radio_actions (action_group,
1127 modest_msg_edit_alignment_radio_action_entries,
1128 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
1130 G_CALLBACK (modest_ui_actions_on_change_justify),
1132 gtk_action_group_add_radio_actions (action_group,
1133 modest_msg_edit_zoom_action_entries,
1134 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
1136 G_CALLBACK (modest_ui_actions_on_change_zoom),
1138 gtk_action_group_add_radio_actions (action_group,
1139 modest_msg_edit_priority_action_entries,
1140 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
1142 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
1144 gtk_action_group_add_radio_actions (action_group,
1145 modest_msg_edit_file_format_action_entries,
1146 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
1147 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
1148 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
1150 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1151 g_object_unref (action_group);
1153 /* Load the UI definition */
1154 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
1156 if (error != NULL) {
1157 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
1158 g_clear_error (&error);
1161 /* Add accelerators */
1162 gtk_window_add_accel_group (GTK_WINDOW (obj),
1163 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1165 /* Menubar. Update the state of some toggles */
1166 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
1167 conf = modest_runtime_get_conf ();
1168 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1169 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
1170 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1171 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL));
1172 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1173 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu");
1174 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1175 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1177 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1180 init_window (MODEST_MSG_EDIT_WINDOW(obj));
1182 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1184 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1186 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1187 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1189 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
1190 if (account_pair != NULL)
1191 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
1193 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1194 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
1195 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
1196 clipboard_rules_group = modest_dimming_rules_group_new ("ModestClipboardDimmingRules", FALSE);
1197 /* Add common dimming rules */
1198 modest_dimming_rules_group_add_rules (menu_rules_group,
1199 modest_msg_edit_window_menu_dimming_entries,
1200 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1201 MODEST_WINDOW (obj));
1202 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1203 modest_msg_edit_window_toolbar_dimming_entries,
1204 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1205 MODEST_WINDOW (obj));
1206 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1207 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1208 MODEST_WINDOW (obj));
1209 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1210 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1211 MODEST_WINDOW (obj));
1212 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1213 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1214 MODEST_WINDOW (obj));
1215 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1216 modest_msg_edit_window_clipboard_dimming_entries,
1217 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1218 MODEST_WINDOW (obj));
1219 /* Insert dimming rules group for this window */
1220 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1221 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1222 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1223 /* Checks the dimming rules */
1224 g_object_unref (menu_rules_group);
1225 g_object_unref (toolbar_rules_group);
1226 g_object_unref (clipboard_rules_group);
1228 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1230 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1232 /* Set window icon */
1233 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
1235 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1236 g_object_unref (window_icon);
1239 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1240 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), "ModestClipboardDimmingRules");
1242 /* Dim at start clipboard actions */
1243 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
1244 gtk_action_set_sensitive (action, FALSE);
1245 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
1246 gtk_action_set_sensitive (action, FALSE);
1247 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
1248 gtk_action_set_sensitive (action, FALSE);
1250 /* set initial state of cc and bcc */
1251 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
1252 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1253 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
1254 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
1255 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1256 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
1258 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), "ModestClipboardDimmingRules");
1259 priv->update_caption_visibility = TRUE;
1261 reset_modified (MODEST_MSG_EDIT_WINDOW (obj));
1263 return (ModestWindow*) obj;
1267 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1269 GString **string_buffer = (GString **) user_data;
1271 *string_buffer = g_string_append (*string_buffer, buffer);
1277 * @result: A new string which should be freed with g_free().
1280 get_formatted_data (ModestMsgEditWindow *edit_window)
1282 ModestMsgEditWindowPrivate *priv;
1283 GString *string_buffer = g_string_new ("");
1285 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1287 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1289 return g_string_free (string_buffer, FALSE);
1294 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1297 const gchar *account_name;
1298 ModestMsgEditWindowPrivate *priv;
1300 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1302 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1304 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1305 g_return_val_if_fail (account_name, NULL);
1308 /* don't free these (except from) */
1309 data = g_slice_new0 (MsgData);
1310 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1312 data->account_name = g_strdup (account_name);
1313 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1314 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1315 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1316 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1317 if (priv->draft_msg) {
1318 data->draft_msg = g_object_ref (priv->draft_msg);
1319 } else if (priv->outbox_msg) {
1320 data->draft_msg = g_object_ref (priv->outbox_msg);
1322 data->draft_msg = NULL;
1325 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1327 gtk_text_buffer_get_bounds (buf, &b, &e);
1328 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1330 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1331 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1333 data->html_body = NULL;
1335 /* deep-copy the data */
1336 GList *cursor = priv->attachments;
1337 data->attachments = NULL;
1339 if (!(TNY_IS_MIME_PART(cursor->data))) {
1340 g_warning ("strange data in attachment list");
1341 cursor = g_list_next (cursor);
1344 data->attachments = g_list_append (data->attachments,
1345 g_object_ref (cursor->data));
1346 cursor = g_list_next (cursor);
1349 data->priority_flags = priv->priority_flags;
1356 unref_gobject (GObject *obj, gpointer data)
1358 if (!G_IS_OBJECT(obj))
1360 g_object_unref (obj);
1364 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1367 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1375 g_free (data->subject);
1376 g_free (data->plain_body);
1377 g_free (data->html_body);
1378 g_free (data->account_name);
1380 if (data->draft_msg != NULL) {
1381 g_object_unref (data->draft_msg);
1382 data->draft_msg = NULL;
1385 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1386 g_list_free (data->attachments);
1388 g_slice_free (MsgData, data);
1392 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1395 ModestMsgEditWindowPrivate *priv = NULL;
1396 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1398 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1400 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1402 return MODEST_MSG_EDIT_FORMAT_HTML;
1404 return MODEST_MSG_EDIT_FORMAT_TEXT;
1408 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1409 ModestMsgEditFormat format)
1411 ModestMsgEditWindowPrivate *priv;
1413 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1414 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1417 case MODEST_MSG_EDIT_FORMAT_HTML:
1418 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1420 case MODEST_MSG_EDIT_FORMAT_TEXT:
1421 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1424 g_return_if_reached ();
1428 ModestMsgEditFormatState *
1429 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1431 ModestMsgEditFormatState *format_state = NULL;
1432 ModestMsgEditWindowPrivate *priv;
1433 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1435 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1436 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1438 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1440 format_state = g_new0 (ModestMsgEditFormatState, 1);
1441 format_state->bold = buffer_format->bold&0x1;
1442 format_state->italics = buffer_format->italic&0x1;
1443 format_state->bullet = buffer_format->bullet&0x1;
1444 format_state->color = buffer_format->color;
1445 format_state->font_size = buffer_format->font_size;
1446 format_state->font_family = wp_get_font_name (buffer_format->font);
1447 format_state->justification = buffer_format->justification;
1448 g_free (buffer_format);
1450 return format_state;
1455 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1456 const ModestMsgEditFormatState *format_state)
1458 ModestMsgEditWindowPrivate *priv;
1459 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1460 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1461 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1462 g_return_if_fail (format_state != NULL);
1464 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1465 gtk_widget_grab_focus (priv->msg_body);
1466 buffer_format->bold = (format_state->bold != FALSE);
1467 buffer_format->italic = (format_state->italics != FALSE);
1468 buffer_format->color = format_state->color;
1469 buffer_format->font_size = format_state->font_size;
1470 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1471 buffer_format->justification = format_state->justification;
1472 buffer_format->bullet = format_state->bullet;
1474 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1476 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1477 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1478 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1479 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1480 buffer_format->cs.font = (buffer_format->font != current_format->font);
1481 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1482 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1484 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1485 if (buffer_format->cs.bold) {
1486 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1488 if (buffer_format->cs.italic) {
1489 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1491 if (buffer_format->cs.color) {
1492 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1494 if (buffer_format->cs.font_size) {
1495 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1497 if (buffer_format->cs.justification) {
1498 switch (buffer_format->justification) {
1499 case GTK_JUSTIFY_LEFT:
1500 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1502 case GTK_JUSTIFY_CENTER:
1503 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1505 case GTK_JUSTIFY_RIGHT:
1506 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1513 if (buffer_format->cs.font) {
1514 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1516 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1517 if (buffer_format->cs.bullet) {
1518 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((buffer_format->bullet)?1:0));
1520 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1522 g_free (current_format);
1527 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1529 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1531 ModestWindowPrivate *parent_priv;
1532 ModestMsgEditWindowPrivate *priv;
1533 GtkWidget *new_size_menuitem;
1534 GtkWidget *new_font_menuitem;
1536 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1537 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1539 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1540 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1541 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1542 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1544 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1545 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1546 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1549 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1551 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1552 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1554 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1555 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1557 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1558 /* modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1560 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1561 G_CALLBACK (modest_msg_edit_window_color_button_change),
1563 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1564 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1565 G_CALLBACK (modest_msg_edit_window_color_button_change),
1568 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1569 buffer_format->font_size))->data);
1570 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1574 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1575 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1576 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1578 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1579 G_CALLBACK (modest_msg_edit_window_size_change),
1581 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1582 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1583 G_CALLBACK (modest_msg_edit_window_size_change),
1587 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1588 buffer_format->font))->data);
1589 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1593 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1594 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1595 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1597 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1598 G_CALLBACK (modest_msg_edit_window_font_change),
1600 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1601 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1602 G_CALLBACK (modest_msg_edit_window_font_change),
1606 g_free (buffer_format);
1612 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1615 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1616 ModestMsgEditWindowPrivate *priv;
1617 GtkWidget *dialog = NULL;
1619 const GdkColor *new_color = NULL;
1621 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1622 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1624 #ifdef MODEST_HILDON_VERSION_0
1625 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1626 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1628 dialog = hildon_color_chooser_new ();
1629 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1630 #endif /*MODEST_HILDON_VERSION_0*/
1631 g_free (buffer_format);
1633 response = gtk_dialog_run (GTK_DIALOG (dialog));
1635 case GTK_RESPONSE_OK: {
1636 #ifdef MODEST_HILDON_VERSION_0
1637 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1640 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1642 #endif /*MODEST_HILDON_VERSION_0*/
1649 gtk_widget_destroy (dialog);
1651 if (new_color != NULL)
1652 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1657 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1660 ModestMsgEditWindowPrivate *priv;
1661 GtkWidget *dialog = NULL;
1663 GdkColor *old_color = NULL;
1664 const GdkColor *new_color = NULL;
1666 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1667 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1669 #ifdef MODEST_HILDON_VERSION_0
1670 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1671 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1673 dialog = hildon_color_chooser_new ();
1674 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1675 #endif /*MODEST_HILDON_VERSION_9*/
1677 response = gtk_dialog_run (GTK_DIALOG (dialog));
1679 case GTK_RESPONSE_OK: {
1680 #ifdef MODEST_HILDON_VERSION_0
1681 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1684 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1686 #endif /*MODEST_HILDON_VERSION_0*/
1692 gtk_widget_destroy (dialog);
1694 if (new_color != NULL)
1695 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1699 static TnyStream* create_stream_for_uri (const gchar* uri)
1704 TnyStream *result = NULL;
1706 GnomeVFSHandle *handle = NULL;
1707 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1708 if (test == GNOME_VFS_OK) {
1709 /* Create the tinymail stream: */
1710 /* Presumably tinymai will call gnome_vfs_close (handle) later. */
1711 result = TNY_STREAM (tny_vfs_stream_new (handle));
1718 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1721 ModestMsgEditWindowPrivate *priv;
1722 GtkWidget *dialog = NULL;
1724 GSList *uris = NULL;
1725 GSList *uri_node = NULL;
1727 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1729 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1730 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1731 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1733 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1735 response = gtk_dialog_run (GTK_DIALOG (dialog));
1737 case GTK_RESPONSE_OK:
1738 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1743 gtk_widget_destroy (dialog);
1745 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1747 GnomeVFSHandle *handle = NULL;
1748 GnomeVFSResult result;
1749 GtkTextIter position;
1750 GtkTextMark *insert_mark;
1752 uri = (const gchar *) uri_node->data;
1753 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1754 if (result == GNOME_VFS_OK) {
1756 GnomeVFSFileInfo info;
1757 gchar *filename, *basename, *escaped_filename;
1758 TnyMimePart *mime_part;
1760 const gchar *mime_type = NULL;
1761 GnomeVFSURI *vfs_uri;
1763 vfs_uri = gnome_vfs_uri_new (uri);
1765 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1766 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1767 g_free (escaped_filename);
1768 gnome_vfs_uri_unref (vfs_uri);
1770 if (gnome_vfs_get_file_info (uri, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
1771 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1773 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1775 mime_part = tny_platform_factory_new_mime_part
1776 (modest_runtime_get_platform_factory ());
1778 TnyStream *stream = create_stream_for_uri (uri);
1779 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1781 content_id = g_strdup_printf ("%d", priv->last_cid);
1782 tny_mime_part_set_content_id (mime_part, content_id);
1783 g_free (content_id);
1786 basename = g_path_get_basename (filename);
1787 tny_mime_part_set_filename (mime_part, basename);
1790 pixbuf = pixbuf_from_stream (stream, mime_type);
1792 if (pixbuf != NULL) {
1793 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1794 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1795 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1798 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1799 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1801 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1802 gtk_widget_show_all (priv->attachments_caption);
1803 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1813 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
1816 ModestMsgEditWindowPrivate *priv;
1817 GtkWidget *dialog = NULL;
1819 GSList *uris = NULL;
1822 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1824 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1825 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
1826 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1828 response = gtk_dialog_run (GTK_DIALOG (dialog));
1830 case GTK_RESPONSE_OK:
1831 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1836 gtk_widget_destroy (dialog);
1838 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1839 const gchar *uri = (const gchar *) uri_node->data;
1840 modest_msg_edit_window_attach_file_one (window, uri);
1842 g_slist_foreach (uris, (GFunc) g_free, NULL);
1843 g_slist_free (uris);
1847 modest_msg_edit_window_attach_file_one (
1848 ModestMsgEditWindow *window,
1851 g_return_if_fail (window);
1852 g_return_if_fail (uri);
1854 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1857 GnomeVFSHandle *handle = NULL;
1858 GnomeVFSResult result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1859 if (result == GNOME_VFS_OK) {
1860 TnyMimePart *mime_part;
1862 const gchar *mime_type = NULL;
1864 gchar *escaped_filename;
1867 GnomeVFSFileInfo info;
1868 GnomeVFSURI *vfs_uri;
1870 vfs_uri = gnome_vfs_uri_new (uri);
1873 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1874 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1875 g_free (escaped_filename);
1876 gnome_vfs_uri_unref (vfs_uri);
1878 if (gnome_vfs_get_file_info (uri,
1880 GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
1881 GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1883 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1884 mime_part = tny_platform_factory_new_mime_part
1885 (modest_runtime_get_platform_factory ());
1886 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1888 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1890 content_id = g_strdup_printf ("%d", priv->last_cid);
1891 tny_mime_part_set_content_id (mime_part, content_id);
1892 g_free (content_id);
1895 basename = g_path_get_basename (filename);
1896 tny_mime_part_set_filename (mime_part, basename);
1899 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1900 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1902 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1903 gtk_widget_show_all (priv->attachments_caption);
1904 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1910 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1913 ModestMsgEditWindowPrivate *priv;
1914 gboolean clean_list = FALSE;
1916 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1917 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1919 if (att_list == NULL) {
1920 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1924 if (att_list == NULL) {
1925 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1927 GtkWidget *confirmation_dialog = NULL;
1928 gboolean dialog_response;
1930 gchar *message = NULL;
1931 const gchar *filename = NULL;
1933 if (att_list->next == NULL) {
1934 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1938 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1939 att_list->next == NULL), filename);
1940 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1942 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1943 gtk_widget_destroy (confirmation_dialog);
1944 if (!dialog_response) {
1946 g_list_free (att_list);
1949 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1951 for (node = att_list; node != NULL; node = g_list_next (node)) {
1952 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1953 const gchar *att_id;
1954 priv->attachments = g_list_remove (priv->attachments, mime_part);
1956 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1958 if (priv->attachments == NULL)
1959 gtk_widget_hide (priv->attachments_caption);
1960 att_id = tny_mime_part_get_content_id (mime_part);
1962 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1964 g_object_unref (mime_part);
1965 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1970 g_list_free (att_list);
1974 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1977 ModestMsgEditWindowPrivate *priv;
1978 GdkColor *new_color;
1979 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1981 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1982 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1985 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1987 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1989 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1991 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1996 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1999 ModestMsgEditWindowPrivate *priv;
2000 gint new_size_index;
2001 ModestMsgEditWindow *window;
2004 window = MODEST_MSG_EDIT_WINDOW (userdata);
2005 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2006 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2008 if (gtk_check_menu_item_get_active (menu_item)) {
2010 WPTextBufferFormat format;
2012 memset (&format, 0, sizeof (format));
2013 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2015 label = gtk_bin_get_child (GTK_BIN (menu_item));
2017 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2018 format.cs.font_size = TRUE;
2019 format.cs.text_position = TRUE;
2020 format.cs.font = TRUE;
2021 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2022 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2024 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2025 (gpointer) wp_get_font_size_index (new_size_index, 12)))
2026 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2028 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2029 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2030 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2036 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2039 ModestMsgEditWindowPrivate *priv;
2040 gint new_font_index;
2041 ModestMsgEditWindow *window;
2044 window = MODEST_MSG_EDIT_WINDOW (userdata);
2045 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2046 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2048 if (gtk_check_menu_item_get_active (menu_item)) {
2051 label = gtk_bin_get_child (GTK_BIN (menu_item));
2053 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2055 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2056 (gpointer) new_font_index))
2057 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2059 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2060 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2061 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2067 modest_msg_edit_window_set_zoom (ModestWindow *window,
2070 ModestMsgEditWindowPrivate *priv;
2071 ModestWindowPrivate *parent_priv;
2072 GtkRadioAction *zoom_radio_action;
2074 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2076 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2077 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2078 priv->zoom_level = zoom;
2079 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom*DEFAULT_FONT_SCALE);
2081 /* Zoom level menu options should be updated with the current zoom level */
2082 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2083 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2084 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2085 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2086 /* FIXME: Not availible before Gtk 2.10 */
2088 gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
2093 modest_msg_edit_window_get_zoom (ModestWindow *window)
2095 ModestMsgEditWindowPrivate *priv;
2097 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
2099 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2100 return priv->zoom_level;
2104 zoom_allowed (ModestMsgEditWindow *window)
2108 focus = gtk_window_get_focus (GTK_WINDOW (window));
2109 return (focus != NULL && WP_IS_TEXT_VIEW (focus));
2113 modest_msg_edit_window_zoom_plus (ModestWindow *window)
2115 ModestWindowPrivate *parent_priv;
2116 GtkRadioAction *zoom_radio_action;
2117 GSList *group, *node;
2119 /* First we check if the text view is focused. If not, zooming is not allowed */
2120 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2121 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2125 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2126 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2127 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2129 group = gtk_radio_action_get_group (zoom_radio_action);
2131 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
2132 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
2136 for (node = group; node != NULL; node = g_slist_next (node)) {
2137 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
2138 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
2146 modest_msg_edit_window_zoom_minus (ModestWindow *window)
2148 ModestWindowPrivate *parent_priv;
2149 GtkRadioAction *zoom_radio_action;
2150 GSList *group, *node;
2152 /* First we check if the text view is focused. If not, zooming is not allowed */
2153 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2154 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2158 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2159 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2160 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2162 group = gtk_radio_action_get_group (zoom_radio_action);
2164 for (node = group; node != NULL; node = g_slist_next (node)) {
2165 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
2166 if (node->next != NULL) {
2167 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
2170 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
2178 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2180 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2181 ModestWindowPrivate *parent_priv;
2182 ModestWindowMgr *mgr;
2183 gboolean is_fullscreen;
2184 GtkAction *fs_toggle_action;
2187 mgr = modest_runtime_get_window_mgr ();
2188 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2190 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2192 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2193 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2194 if (is_fullscreen != active)
2195 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2203 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2206 ModestMsgEditWindowPrivate *priv = NULL;
2207 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2209 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2210 if (!priv->update_caption_visibility)
2213 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2215 gtk_widget_show (priv->cc_caption);
2217 gtk_widget_hide (priv->cc_caption);
2219 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2223 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2226 ModestMsgEditWindowPrivate *priv = NULL;
2227 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2229 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2230 if (!priv->update_caption_visibility)
2233 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2235 gtk_widget_show (priv->bcc_caption);
2237 gtk_widget_hide (priv->bcc_caption);
2239 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2243 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2244 ModestRecptEditor *editor)
2246 ModestMsgEditWindowPrivate *priv;
2248 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2249 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2250 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2252 if (editor == NULL) {
2253 GtkWidget *view_focus;
2254 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2256 /* This code should be kept in sync with ModestRecptEditor. The
2257 textview inside the recpt editor is the one that really gets the
2258 focus. As it's inside a scrolled window, and this one inside the
2259 hbox recpt editor inherits from, we'll need to go up in the
2260 hierarchy to know if the text view is part of the recpt editor
2261 or if it's a different text entry */
2263 if (gtk_widget_get_parent (view_focus)) {
2264 GtkWidget *first_parent;
2266 first_parent = gtk_widget_get_parent (view_focus);
2267 if (gtk_widget_get_parent (first_parent) &&
2268 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2269 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2274 editor = MODEST_RECPT_EDITOR (priv->to_field);
2278 modest_address_book_select_addresses (editor);
2283 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2285 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2287 modest_msg_edit_window_open_addressbook (window, NULL);
2291 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2292 gboolean show_toolbar)
2294 ModestWindowPrivate *parent_priv;
2295 const gchar *action_name;
2298 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2299 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2301 /* We can not just use the code of
2302 modest_msg_edit_window_setup_toolbar because it has a
2303 mixture of both initialization and creation code. */
2305 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2307 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2309 /* Update also the actions (to update the toggles in the
2310 menus), we have to do it manually because some other window
2311 of the same time could have changed it (remember that the
2312 toolbar fullscreen mode is shared by all the windows of the
2314 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2315 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2317 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2319 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2320 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2326 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2327 TnyHeaderFlags priority_flags)
2329 ModestMsgEditWindowPrivate *priv;
2330 ModestWindowPrivate *parent_priv;
2332 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2334 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2335 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2336 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2338 if (priv->priority_flags != priority_flags) {
2339 GtkAction *priority_action = NULL;
2341 priv->priority_flags = priority_flags;
2343 switch (priority_flags) {
2344 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2345 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2346 gtk_widget_show (priv->priority_icon);
2347 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2348 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2350 case TNY_HEADER_FLAG_LOW_PRIORITY:
2351 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2352 gtk_widget_show (priv->priority_icon);
2353 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2354 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2357 gtk_widget_hide (priv->priority_icon);
2358 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2359 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2362 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2363 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2368 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2371 ModestMsgEditWindowPrivate *priv;
2372 ModestWindowPrivate *parent_priv;
2373 gint current_format;
2375 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2377 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2378 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2380 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2381 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2383 if (current_format != file_format) {
2384 switch (file_format) {
2385 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2386 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2388 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2392 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2393 response = gtk_dialog_run (GTK_DIALOG (dialog));
2394 gtk_widget_destroy (dialog);
2395 if (response == GTK_RESPONSE_OK) {
2396 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2398 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2399 modest_maemo_toggle_action_set_active_block_notify (action, TRUE);
2404 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2409 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2412 ModestMsgEditWindowPrivate *priv;
2413 WPTextBufferFormat oldfmt, fmt;
2414 gint old_position = 0;
2418 GdkColor *color = NULL;
2419 gboolean bold, bold_set, italic, italic_set;
2420 gboolean underline, underline_set;
2421 gboolean strikethrough, strikethrough_set;
2422 gboolean position_set;
2423 gboolean font_size_set, font_set, color_set;
2426 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2427 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2429 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2431 /* First we get the currently selected font information */
2432 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2433 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2435 switch (oldfmt.text_position) {
2436 case TEXT_POSITION_NORMAL:
2439 case TEXT_POSITION_SUPERSCRIPT:
2447 g_object_set (G_OBJECT (dialog),
2448 "bold", oldfmt.bold != FALSE,
2449 "bold-set", !oldfmt.cs.bold,
2450 "underline", oldfmt.underline != FALSE,
2451 "underline-set", !oldfmt.cs.underline,
2452 "italic", oldfmt.italic != FALSE,
2453 "italic-set", !oldfmt.cs.italic,
2454 "strikethrough", oldfmt.strikethrough != FALSE,
2455 "strikethrough-set", !oldfmt.cs.strikethrough,
2456 "color", &oldfmt.color,
2457 "color-set", !oldfmt.cs.color,
2458 "size", wp_font_size[oldfmt.font_size],
2459 "size-set", !oldfmt.cs.font_size,
2460 "position", old_position,
2461 "position-set", !oldfmt.cs.text_position,
2462 "family", wp_get_font_name (oldfmt.font),
2463 "family-set", !oldfmt.cs.font,
2466 gtk_widget_show_all (dialog);
2467 response = gtk_dialog_run (GTK_DIALOG (dialog));
2468 if (response == GTK_RESPONSE_OK) {
2470 g_object_get( dialog,
2472 "bold-set", &bold_set,
2473 "underline", &underline,
2474 "underline-set", &underline_set,
2476 "italic-set", &italic_set,
2477 "strikethrough", &strikethrough,
2478 "strikethrough-set", &strikethrough_set,
2480 "color-set", &color_set,
2482 "size-set", &font_size_set,
2483 "family", &font_name,
2484 "family-set", &font_set,
2485 "position", &position,
2486 "position-set", &position_set,
2491 if (response == GTK_RESPONSE_OK) {
2492 memset(&fmt, 0, sizeof(fmt));
2498 fmt.italic = italic;
2499 fmt.cs.italic = TRUE;
2501 if (underline_set) {
2502 fmt.underline = underline;
2503 fmt.cs.underline = TRUE;
2505 if (strikethrough_set) {
2506 fmt.strikethrough = strikethrough;
2507 fmt.cs.strikethrough = TRUE;
2512 ? TEXT_POSITION_NORMAL
2513 : ( ( position == 1 )
2514 ? TEXT_POSITION_SUPERSCRIPT
2515 : TEXT_POSITION_SUBSCRIPT );
2516 fmt.cs.text_position = TRUE;
2520 fmt.cs.color = TRUE;
2523 fmt.font = wp_get_font_index(font_name,
2528 if (font_size_set) {
2529 fmt.font_size = wp_get_font_size_index(
2530 font_size, DEFAULT_FONT_SIZE);
2531 fmt.cs.font_size = TRUE;
2533 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2535 gtk_widget_destroy (dialog);
2537 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2541 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2543 ModestMsgEditWindowPrivate *priv;
2545 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2546 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2548 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2550 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2555 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2557 ModestMsgEditWindowPrivate *priv;
2559 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2560 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2562 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2564 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2569 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2571 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2573 priv->can_undo = can_undo;
2577 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2579 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2581 priv->can_redo = can_redo;
2585 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2587 ModestMsgEditWindowPrivate *priv;
2588 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2589 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2591 return priv->can_undo;
2595 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2597 ModestMsgEditWindowPrivate *priv;
2598 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2599 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2601 return priv->can_redo;
2606 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2609 GtkTextIter match_start, match_end;
2611 if (image_id == NULL)
2614 gtk_text_buffer_get_start_iter (buffer, &iter);
2616 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2617 GSList *tags = gtk_text_iter_get_tags (&match_start);
2619 for (node = tags; node != NULL; node = g_slist_next (node)) {
2620 GtkTextTag *tag = (GtkTextTag *) node->data;
2621 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2622 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2623 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2625 offset = gtk_text_iter_get_offset (&match_start);
2626 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2627 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2631 gtk_text_iter_forward_char (&iter);
2636 message_is_empty (ModestMsgEditWindow *window)
2638 ModestMsgEditWindowPrivate *priv = NULL;
2640 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2641 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2643 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
2644 * so we can ignore markup.
2646 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
2649 count = gtk_text_buffer_get_char_count (buf);
2655 msg_body_focus (GtkWidget *focus,
2656 GdkEventFocus *event,
2660 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
2665 recpt_field_changed (GtkTextBuffer *buffer,
2666 ModestMsgEditWindow *editor)
2668 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
2672 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
2674 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
2678 reset_modified (ModestMsgEditWindow *editor)
2680 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2681 GtkTextBuffer *buffer;
2683 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2684 gtk_text_buffer_set_modified (buffer, FALSE);
2685 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2686 gtk_text_buffer_set_modified (buffer, FALSE);
2687 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2688 gtk_text_buffer_set_modified (buffer, FALSE);
2689 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2693 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2695 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2696 GtkTextBuffer *buffer;
2698 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2699 if (gtk_text_buffer_get_modified (buffer))
2701 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2702 if (gtk_text_buffer_get_modified (buffer))
2704 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2705 if (gtk_text_buffer_get_modified (buffer))
2707 if (gtk_text_buffer_get_modified (priv->text_buffer))
2717 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
2719 ModestMsgEditWindowPrivate *priv = NULL;
2721 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2722 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2724 /* check if there's no recipient added */
2725 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2726 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2727 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2728 /* no recipient contents, then select contacts */
2729 modest_msg_edit_window_open_addressbook (window, NULL);
2733 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
2734 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2737 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
2738 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
2741 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
2742 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
2746 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
2747 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
2748 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2755 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2756 ModestMsgEditWindow *window)
2758 modest_msg_edit_window_offer_attach_file (window);
2762 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2764 ModestMsgEditWindow *window)
2766 if (!GTK_WIDGET_VISIBLE (window))
2769 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), "ModestClipboardDimmingRules");
2772 subject_field_move_cursor (GtkEntry *entry,
2773 GtkMovementStep step,
2778 if (!GTK_WIDGET_VISIBLE (window))
2781 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), "ModestClipboardDimmingRules");
2785 update_window_title (ModestMsgEditWindow *window)
2787 ModestMsgEditWindowPrivate *priv = NULL;
2788 const gchar *subject;
2790 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2791 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2792 if (subject == NULL || subject[0] == '\0')
2793 subject = _("mail_va_new_email");
2795 gtk_window_set_title (GTK_WINDOW (window), subject);
2800 subject_field_changed (GtkEditable *editable,
2801 ModestMsgEditWindow *window)
2803 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2804 update_window_title (window);
2805 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2806 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2810 subject_field_insert_text (GtkEditable *editable,
2812 gint new_text_length,
2814 ModestMsgEditWindow *window)
2816 GString *result = g_string_new ("");
2818 gint result_len = 0;
2820 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
2821 gunichar c = g_utf8_get_char_validated (current, 8);
2822 /* Invalid unichar, stop */
2828 result = g_string_append_unichar (result, c);
2832 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
2833 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
2836 /* Prevent endless recursion */
2837 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
2838 g_signal_emit_by_name (editable, "insert-text",
2839 (gpointer) result->str, (gpointer) result->len,
2840 (gpointer) position, (gpointer) window);
2841 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
2845 g_string_free (result, TRUE);
2849 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2852 ModestMsgEditWindowPrivate *priv = NULL;
2854 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2855 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2857 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2860 gtk_widget_show_all (priv->find_toolbar);
2861 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2863 gtk_widget_hide_all (priv->find_toolbar);
2864 gtk_widget_grab_focus (priv->msg_body);
2870 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2872 GtkTextIter *match_start,
2873 GtkTextIter *match_end)
2875 GtkTextIter end_iter;
2876 gchar *str_casefold;
2879 gchar *range_casefold;
2882 gboolean result = FALSE;
2889 gtk_text_iter_forward_to_end (&end_iter);
2891 str_casefold = g_utf8_casefold (str, -1);
2892 str_chars_n = strlen (str);
2894 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2895 range_casefold = g_utf8_casefold (range_text, -1);
2896 range_chars_n = strlen (range_casefold);
2898 if (range_chars_n < str_chars_n) {
2899 g_free (str_casefold);
2900 g_free (range_text);
2901 g_free (range_casefold);
2905 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2906 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2907 if (!g_utf8_collate (range_subtext, str_casefold)) {
2908 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2910 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2911 match_start, match_end, NULL);
2912 g_free (found_text);
2914 g_free (range_subtext);
2918 g_free (str_casefold);
2919 g_free (range_text);
2920 g_free (range_casefold);
2927 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2928 ModestMsgEditWindow *window)
2930 gchar *current_search = NULL;
2931 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2933 GtkTextIter selection_start, selection_end;
2934 GtkTextIter match_start, match_end;
2935 gboolean continue_search = FALSE;
2937 if (message_is_empty (window)) {
2938 g_free (priv->last_search);
2939 priv->last_search = NULL;
2940 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
2944 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2945 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2946 g_free (current_search);
2947 g_free (priv->last_search);
2948 priv->last_search = NULL;
2949 /* Information banner about empty search */
2950 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2954 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2955 continue_search = TRUE;
2957 g_free (priv->last_search);
2958 priv->last_search = g_strdup (current_search);
2961 if (continue_search) {
2962 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2963 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2964 &match_start, &match_end);
2966 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2968 GtkTextIter buffer_start;
2969 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2970 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2971 &match_start, &match_end);
2973 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2976 /* Mark as selected the string found in search */
2978 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2979 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2981 g_free (priv->last_search);
2982 priv->last_search = NULL;
2984 g_free (current_search);
2988 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2989 ModestMsgEditWindow *window)
2991 GtkToggleAction *toggle;
2992 ModestWindowPrivate *parent_priv;
2993 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2995 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2996 gtk_toggle_action_set_active (toggle, FALSE);
3000 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3002 ModestMsgEditWindowPrivate *priv;
3004 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3009 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3012 ModestMsgEditWindowPrivate *priv;
3014 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3020 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3023 ModestMsgEditWindowPrivate *priv;
3024 TnyHeader *header = NULL;
3026 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3027 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3029 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3030 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3032 if (priv->draft_msg != NULL) {
3033 header = tny_msg_get_header (priv->draft_msg);
3034 if (TNY_IS_HEADER (header)) {
3035 modest_window_mgr_unregister_header (mgr, header);
3037 g_object_unref (priv->draft_msg);
3040 if (draft != NULL) {
3041 g_object_ref (draft);
3042 header = tny_msg_get_header (draft);
3043 if (TNY_IS_HEADER (header))
3044 modest_window_mgr_register_header (mgr, header);
3045 if (priv->msg_uid) {
3046 g_free (priv->msg_uid);
3047 priv->msg_uid = NULL;
3049 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3052 priv->draft_msg = draft;
3056 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3057 GtkTextIter *start, GtkTextIter *end,
3060 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3061 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3064 if (tag == NULL+13) return;
3065 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3066 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3067 replace_with_attachments (window, priv->attachments);
3072 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3075 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3077 g_return_if_fail (TNY_IS_MIME_PART (part));
3078 priv->attachments = g_list_prepend (priv->attachments, part);
3079 g_object_ref (part);
3080 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part);
3081 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3082 gtk_widget_show_all (priv->attachments_caption);
3083 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3087 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3089 ModestMsgEditWindowPrivate *priv;
3091 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3092 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3094 return priv->msg_uid;
3098 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3099 ModestMsgEditWindowWidgetType widget_type)
3101 ModestMsgEditWindowPrivate *priv;
3103 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3104 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3106 switch (widget_type) {
3107 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3108 return priv->msg_body;
3110 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3111 return priv->to_field;
3113 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3114 return priv->cc_field;
3116 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3117 return priv->bcc_field;
3119 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3120 return priv->subject_field;
3122 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3123 return priv->attachments_view;