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 (g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
617 priv->clipboard_change_handler_id))
618 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
619 priv->clipboard_change_handler_id);
620 if (g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
621 priv->default_clipboard_change_handler_id))
622 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
623 priv->default_clipboard_change_handler_id);
627 modest_msg_edit_window_finalize (GObject *obj)
629 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
631 /* Sanity check: shouldn't be needed, the window mgr should
632 call this function before */
633 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
635 if (priv->draft_msg != NULL) {
636 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
637 if (TNY_IS_HEADER (header)) {
638 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
639 modest_window_mgr_unregister_header (mgr, header);
641 g_object_unref (priv->draft_msg);
642 priv->draft_msg = NULL;
644 if (priv->outbox_msg != NULL) {
645 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
646 if (TNY_IS_HEADER (header)) {
647 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
648 modest_window_mgr_unregister_header (mgr, header);
650 g_object_unref (priv->outbox_msg);
651 priv->outbox_msg = NULL;
653 if (priv->msg_uid != NULL) {
654 g_free (priv->msg_uid);
655 priv->msg_uid = NULL;
658 /* This had to stay alive for as long as the combobox that used it: */
659 modest_pair_list_free (priv->from_field_protos);
661 G_OBJECT_CLASS(parent_class)->finalize (obj);
665 menubar_to_menu (GtkUIManager *ui_manager)
667 GtkWidget *main_menu;
671 /* Create new main menu */
672 main_menu = gtk_menu_new();
674 /* Get the menubar from the UI manager */
675 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
677 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
681 menu = GTK_WIDGET (iter->data);
682 gtk_widget_reparent(menu, main_menu);
684 iter = g_list_next (iter);
690 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type)
692 GdkPixbufLoader *loader;
695 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
700 tny_stream_reset (TNY_STREAM (stream));
701 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
702 unsigned char read_buffer[128];
704 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
705 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
709 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
710 g_object_ref (pixbuf);
711 gdk_pixbuf_loader_close (loader, NULL);
712 g_object_unref (loader);
714 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
715 GdkPixbuf *new_pixbuf;
717 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
718 gdk_pixbuf_get_width (pixbuf);
719 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
720 g_object_unref (pixbuf);
728 replace_with_attachments (ModestMsgEditWindow *self, GList *attachments)
730 ModestMsgEditWindowPrivate *priv;
733 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
735 for (node = attachments; node != NULL; node = g_list_next (node)) {
736 TnyMimePart *part = (TnyMimePart *) node->data;
737 const gchar *cid = tny_mime_part_get_content_id (part);
738 const gchar *mime_type = tny_mime_part_get_content_type (part);
739 if ((cid != NULL)&&(mime_type != NULL)) {
740 TnyStream *stream = tny_mime_part_get_stream (part);
741 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type);
742 g_object_unref (stream);
744 if (pixbuf != NULL) {
745 /* wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf); */
746 g_object_unref (pixbuf);
753 update_last_cid (ModestMsgEditWindow *self, GList *attachments)
756 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
758 for (node = attachments; node != NULL; node = g_list_next (node)) {
759 TnyMimePart *part = (TnyMimePart *) node->data;
760 const gchar *cid = tny_mime_part_get_content_id (part);
762 char *invalid = NULL;
763 gint int_cid = strtol (cid, &invalid, 10);
764 if ((invalid != NULL) && (*invalid == '\0') && (int_cid > priv->last_cid)) {
765 priv->last_cid = int_cid;
773 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
776 const gchar *to, *cc, *bcc, *subject;
778 ModestMsgEditWindowPrivate *priv;
780 TnyHeaderFlags priority_flags;
781 TnyFolder *msg_folder;
782 gboolean is_html = FALSE;
784 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
785 g_return_if_fail (TNY_IS_MSG (msg));
787 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
789 header = tny_msg_get_header (msg);
790 to = tny_header_get_to (header);
791 cc = tny_header_get_cc (header);
792 bcc = tny_header_get_bcc (header);
793 subject = tny_header_get_subject (header);
794 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
797 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
799 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
800 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
801 gtk_widget_show (priv->cc_caption);
802 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
803 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
804 gtk_widget_hide (priv->cc_caption);
807 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
808 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
809 gtk_widget_show (priv->bcc_caption);
810 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
811 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
812 gtk_widget_hide (priv->bcc_caption);
815 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
816 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
819 update_window_title (self);
821 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
822 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
824 if ((body == NULL)||(body[0] == '\0')) {
826 body = modest_text_utils_convert_to_html ("");
829 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
830 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
833 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
836 if (preserve_is_rich && !is_html) {
837 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
838 /* Get the default format required from configuration */
839 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
840 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
843 /* Set the default focus depending on having already a To: field or not */
844 if ((!to)||(*to == '\0')) {
845 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
847 gtk_widget_grab_focus (priv->msg_body);
850 /* TODO: lower priority, select in the From: combo to the
851 value that comes from msg <- not sure, should it be
854 /* Add attachments to the view */
855 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
856 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
857 if (priv->attachments == NULL) {
858 gtk_widget_hide (priv->attachments_caption);
860 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
861 gtk_widget_show_all (priv->attachments_caption);
862 replace_with_attachments (self, priv->attachments);
864 update_last_cid (self, priv->attachments);
866 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
868 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
869 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
871 reset_modified (self);
873 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
874 text_buffer_can_undo (priv->text_buffer, FALSE, self);
875 text_buffer_can_redo (priv->text_buffer, FALSE, self);
878 g_free (priv->msg_uid);
879 priv->msg_uid = NULL;
882 /* we should set a reference to the incoming message if it is a draft */
883 msg_folder = tny_msg_get_folder (msg);
885 if (modest_tny_folder_is_local_folder (msg_folder)) {
886 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
887 if (type == TNY_FOLDER_TYPE_DRAFTS)
888 priv->draft_msg = g_object_ref(msg);
889 if (type == TNY_FOLDER_TYPE_OUTBOX)
890 priv->outbox_msg = g_object_ref(msg);
891 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
893 g_object_unref (msg_folder);
898 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
901 GList *item_children, *node;
902 GtkWidget *bin_child;
904 bin_child = gtk_bin_get_child (GTK_BIN(item));
906 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
908 for (node = item_children; node != NULL; node = g_list_next (node)) {
909 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
910 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
913 g_list_free (item_children);
917 menu_tool_button_dont_expand (GtkMenuToolButton *item)
920 GList *item_children, *node;
922 box = gtk_bin_get_child (GTK_BIN (item));
923 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
924 item_children = gtk_container_get_children (GTK_CONTAINER (box));
926 for (node = item_children; node != NULL; node = g_list_next (node)) {
927 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
928 if (GTK_IS_TOGGLE_BUTTON (node->data))
929 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
930 else if (GTK_IS_BUTTON (node->data))
931 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
933 g_list_free (item_children);
938 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
940 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
941 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
942 GtkWidget *placeholder;
943 GtkWidget *tool_item;
948 GtkWidget *sizes_menu;
949 GtkWidget *fonts_menu;
950 GSList *radio_group = NULL;
955 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
956 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
958 /* Font color placeholder */
959 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
960 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
963 tool_item = GTK_WIDGET (gtk_tool_item_new ());
964 priv->font_color_button = hildon_color_button_new ();
965 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
966 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
967 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
968 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
969 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
970 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
971 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
973 G_CALLBACK (modest_msg_edit_window_color_button_change),
976 /* Font size and face placeholder */
977 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
978 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
980 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
981 priv->size_tool_button_label = gtk_label_new (NULL);
982 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
983 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
984 size_text,"</span>", NULL);
985 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
987 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
988 sizes_menu = gtk_menu_new ();
989 priv->size_items_group = NULL;
991 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
992 GtkWidget *size_menu_item;
994 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
995 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
996 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
997 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
998 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
999 gtk_widget_show (size_menu_item);
1001 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1005 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1006 GtkWidget *item = (GtkWidget *) node->data;
1007 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1011 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1012 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1013 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1014 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1015 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1016 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1017 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1018 priv->font_size_toolitem = tool_item;
1021 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1022 priv->font_tool_button_label = gtk_label_new (NULL);
1023 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1024 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1026 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1027 fonts_menu = gtk_menu_new ();
1028 priv->font_items_group = NULL;
1030 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1031 GtkWidget *font_menu_item;
1032 GtkWidget *child_label;
1034 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1035 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1036 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1037 wp_get_font_name (font_index), "</span>", NULL);
1038 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1041 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1042 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1043 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1044 gtk_widget_show (font_menu_item);
1046 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1049 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1050 GtkWidget *item = (GtkWidget *) node->data;
1051 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1054 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1055 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1056 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1057 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1058 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1059 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1060 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1061 priv->font_face_toolitem = tool_item;
1063 /* Set expand and homogeneous for remaining items */
1064 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1065 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1066 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1067 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1068 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1069 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1070 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1071 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1072 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1074 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1075 will not show the tool items added to the placeholders) */
1076 gtk_widget_show_all (parent_priv->toolbar);
1078 /* Set the no show all *after* showing all items. We do not
1079 want the toolbar to be shown with a show all because it
1080 could go agains the gconf setting regarding showing or not
1081 the toolbar of the editor window */
1082 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1088 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1091 ModestWindowPrivate *parent_priv;
1092 ModestMsgEditWindowPrivate *priv;
1093 GtkActionGroup *action_group;
1094 GError *error = NULL;
1095 GdkPixbuf *window_icon = NULL;
1098 ModestPair *account_pair = NULL;
1099 ModestDimmingRulesGroup *menu_rules_group = NULL;
1100 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1101 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1103 g_return_val_if_fail (msg, NULL);
1104 g_return_val_if_fail (account_name, NULL);
1106 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
1108 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1109 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1111 parent_priv->ui_manager = gtk_ui_manager_new();
1112 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
1113 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1115 /* Add common actions */
1116 gtk_action_group_add_actions (action_group,
1117 modest_msg_edit_action_entries,
1118 G_N_ELEMENTS (modest_msg_edit_action_entries),
1120 gtk_action_group_add_toggle_actions (action_group,
1121 modest_msg_edit_toggle_action_entries,
1122 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
1124 gtk_action_group_add_radio_actions (action_group,
1125 modest_msg_edit_alignment_radio_action_entries,
1126 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
1128 G_CALLBACK (modest_ui_actions_on_change_justify),
1130 gtk_action_group_add_radio_actions (action_group,
1131 modest_msg_edit_zoom_action_entries,
1132 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
1134 G_CALLBACK (modest_ui_actions_on_change_zoom),
1136 gtk_action_group_add_radio_actions (action_group,
1137 modest_msg_edit_priority_action_entries,
1138 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
1140 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
1142 gtk_action_group_add_radio_actions (action_group,
1143 modest_msg_edit_file_format_action_entries,
1144 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
1145 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
1146 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
1148 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1149 g_object_unref (action_group);
1151 /* Load the UI definition */
1152 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
1154 if (error != NULL) {
1155 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
1156 g_clear_error (&error);
1159 /* Add accelerators */
1160 gtk_window_add_accel_group (GTK_WINDOW (obj),
1161 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1163 /* Menubar. Update the state of some toggles */
1164 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
1165 conf = modest_runtime_get_conf ();
1166 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1167 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
1168 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1169 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL));
1170 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1171 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu");
1172 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1173 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1175 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1178 init_window (MODEST_MSG_EDIT_WINDOW(obj));
1180 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1182 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1184 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1185 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1187 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
1188 if (account_pair != NULL)
1189 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
1191 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1192 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
1193 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
1194 clipboard_rules_group = modest_dimming_rules_group_new ("ModestClipboardDimmingRules", FALSE);
1195 /* Add common dimming rules */
1196 modest_dimming_rules_group_add_rules (menu_rules_group,
1197 modest_msg_edit_window_menu_dimming_entries,
1198 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1199 MODEST_WINDOW (obj));
1200 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1201 modest_msg_edit_window_toolbar_dimming_entries,
1202 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1203 MODEST_WINDOW (obj));
1204 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1205 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1206 MODEST_WINDOW (obj));
1207 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1208 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1209 MODEST_WINDOW (obj));
1210 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1211 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1212 MODEST_WINDOW (obj));
1213 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1214 modest_msg_edit_window_clipboard_dimming_entries,
1215 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1216 MODEST_WINDOW (obj));
1217 /* Insert dimming rules group for this window */
1218 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1219 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1220 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1221 /* Checks the dimming rules */
1222 g_object_unref (menu_rules_group);
1223 g_object_unref (toolbar_rules_group);
1224 g_object_unref (clipboard_rules_group);
1226 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1228 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1230 /* Set window icon */
1231 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
1233 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1234 g_object_unref (window_icon);
1237 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1238 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), "ModestClipboardDimmingRules");
1240 /* Dim at start clipboard actions */
1241 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
1242 gtk_action_set_sensitive (action, FALSE);
1243 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
1244 gtk_action_set_sensitive (action, FALSE);
1245 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
1246 gtk_action_set_sensitive (action, FALSE);
1248 /* set initial state of cc and bcc */
1249 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
1250 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1251 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
1252 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
1253 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1254 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
1256 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), "ModestClipboardDimmingRules");
1257 priv->update_caption_visibility = TRUE;
1259 reset_modified (MODEST_MSG_EDIT_WINDOW (obj));
1261 return (ModestWindow*) obj;
1265 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1267 GString **string_buffer = (GString **) user_data;
1269 *string_buffer = g_string_append (*string_buffer, buffer);
1275 * @result: A new string which should be freed with g_free().
1278 get_formatted_data (ModestMsgEditWindow *edit_window)
1280 ModestMsgEditWindowPrivate *priv;
1281 GString *string_buffer = g_string_new ("");
1283 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1285 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1287 return g_string_free (string_buffer, FALSE);
1292 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1295 const gchar *account_name;
1296 ModestMsgEditWindowPrivate *priv;
1298 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1300 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1302 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1303 g_return_val_if_fail (account_name, NULL);
1306 /* don't free these (except from) */
1307 data = g_slice_new0 (MsgData);
1308 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1310 data->account_name = g_strdup (account_name);
1311 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1312 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1313 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1314 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1315 if (priv->draft_msg) {
1316 data->draft_msg = g_object_ref (priv->draft_msg);
1317 } else if (priv->outbox_msg) {
1318 data->draft_msg = g_object_ref (priv->outbox_msg);
1320 data->draft_msg = NULL;
1323 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1325 gtk_text_buffer_get_bounds (buf, &b, &e);
1326 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1328 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1329 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1331 data->html_body = NULL;
1333 /* deep-copy the data */
1334 GList *cursor = priv->attachments;
1335 data->attachments = NULL;
1337 if (!(TNY_IS_MIME_PART(cursor->data))) {
1338 g_warning ("strange data in attachment list");
1339 cursor = g_list_next (cursor);
1342 data->attachments = g_list_append (data->attachments,
1343 g_object_ref (cursor->data));
1344 cursor = g_list_next (cursor);
1347 data->priority_flags = priv->priority_flags;
1354 unref_gobject (GObject *obj, gpointer data)
1356 if (!G_IS_OBJECT(obj))
1358 g_object_unref (obj);
1362 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1365 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1373 g_free (data->subject);
1374 g_free (data->plain_body);
1375 g_free (data->html_body);
1376 g_free (data->account_name);
1378 if (data->draft_msg != NULL) {
1379 g_object_unref (data->draft_msg);
1380 data->draft_msg = NULL;
1383 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1384 g_list_free (data->attachments);
1386 g_slice_free (MsgData, data);
1390 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1393 ModestMsgEditWindowPrivate *priv = NULL;
1394 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1396 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1398 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1400 return MODEST_MSG_EDIT_FORMAT_HTML;
1402 return MODEST_MSG_EDIT_FORMAT_TEXT;
1406 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1407 ModestMsgEditFormat format)
1409 ModestMsgEditWindowPrivate *priv;
1411 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1412 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1415 case MODEST_MSG_EDIT_FORMAT_HTML:
1416 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1418 case MODEST_MSG_EDIT_FORMAT_TEXT:
1419 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1422 g_return_if_reached ();
1426 ModestMsgEditFormatState *
1427 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1429 ModestMsgEditFormatState *format_state = NULL;
1430 ModestMsgEditWindowPrivate *priv;
1431 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1433 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1434 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1436 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1438 format_state = g_new0 (ModestMsgEditFormatState, 1);
1439 format_state->bold = buffer_format->bold&0x1;
1440 format_state->italics = buffer_format->italic&0x1;
1441 format_state->bullet = buffer_format->bullet&0x1;
1442 format_state->color = buffer_format->color;
1443 format_state->font_size = buffer_format->font_size;
1444 format_state->font_family = wp_get_font_name (buffer_format->font);
1445 format_state->justification = buffer_format->justification;
1446 g_free (buffer_format);
1448 return format_state;
1453 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1454 const ModestMsgEditFormatState *format_state)
1456 ModestMsgEditWindowPrivate *priv;
1457 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1458 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1459 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1460 g_return_if_fail (format_state != NULL);
1462 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1463 gtk_widget_grab_focus (priv->msg_body);
1464 buffer_format->bold = (format_state->bold != FALSE);
1465 buffer_format->italic = (format_state->italics != FALSE);
1466 buffer_format->color = format_state->color;
1467 buffer_format->font_size = format_state->font_size;
1468 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1469 buffer_format->justification = format_state->justification;
1470 buffer_format->bullet = format_state->bullet;
1472 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1474 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1475 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1476 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1477 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1478 buffer_format->cs.font = (buffer_format->font != current_format->font);
1479 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1480 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1482 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1483 if (buffer_format->cs.bold) {
1484 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1486 if (buffer_format->cs.italic) {
1487 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1489 if (buffer_format->cs.color) {
1490 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1492 if (buffer_format->cs.font_size) {
1493 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1495 if (buffer_format->cs.justification) {
1496 switch (buffer_format->justification) {
1497 case GTK_JUSTIFY_LEFT:
1498 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1500 case GTK_JUSTIFY_CENTER:
1501 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1503 case GTK_JUSTIFY_RIGHT:
1504 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1511 if (buffer_format->cs.font) {
1512 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1514 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1515 if (buffer_format->cs.bullet) {
1516 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((buffer_format->bullet)?1:0));
1518 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1520 g_free (current_format);
1525 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1527 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1529 ModestWindowPrivate *parent_priv;
1530 ModestMsgEditWindowPrivate *priv;
1531 GtkWidget *new_size_menuitem;
1532 GtkWidget *new_font_menuitem;
1534 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1535 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1537 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1538 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1539 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1540 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1542 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1543 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1544 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1547 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1549 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1550 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1552 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1553 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1555 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1556 /* modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1558 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1559 G_CALLBACK (modest_msg_edit_window_color_button_change),
1561 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1562 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1563 G_CALLBACK (modest_msg_edit_window_color_button_change),
1566 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1567 buffer_format->font_size))->data);
1568 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1572 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1573 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1574 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1576 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1577 G_CALLBACK (modest_msg_edit_window_size_change),
1579 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1580 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1581 G_CALLBACK (modest_msg_edit_window_size_change),
1585 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1586 buffer_format->font))->data);
1587 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1591 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1592 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1593 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1595 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1596 G_CALLBACK (modest_msg_edit_window_font_change),
1598 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1599 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1600 G_CALLBACK (modest_msg_edit_window_font_change),
1604 g_free (buffer_format);
1610 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1613 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1614 ModestMsgEditWindowPrivate *priv;
1615 GtkWidget *dialog = NULL;
1617 const GdkColor *new_color = NULL;
1619 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1620 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1622 #ifdef MODEST_HILDON_VERSION_0
1623 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1624 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1626 dialog = hildon_color_chooser_new ();
1627 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1628 #endif /*MODEST_HILDON_VERSION_0*/
1629 g_free (buffer_format);
1631 response = gtk_dialog_run (GTK_DIALOG (dialog));
1633 case GTK_RESPONSE_OK: {
1634 #ifdef MODEST_HILDON_VERSION_0
1635 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1638 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1640 #endif /*MODEST_HILDON_VERSION_0*/
1647 gtk_widget_destroy (dialog);
1649 if (new_color != NULL)
1650 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1655 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1658 ModestMsgEditWindowPrivate *priv;
1659 GtkWidget *dialog = NULL;
1661 GdkColor *old_color = NULL;
1662 const GdkColor *new_color = NULL;
1664 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1665 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1667 #ifdef MODEST_HILDON_VERSION_0
1668 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1669 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1671 dialog = hildon_color_chooser_new ();
1672 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1673 #endif /*MODEST_HILDON_VERSION_9*/
1675 response = gtk_dialog_run (GTK_DIALOG (dialog));
1677 case GTK_RESPONSE_OK: {
1678 #ifdef MODEST_HILDON_VERSION_0
1679 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1682 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1684 #endif /*MODEST_HILDON_VERSION_0*/
1690 gtk_widget_destroy (dialog);
1692 if (new_color != NULL)
1693 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1697 static TnyStream* create_stream_for_uri (const gchar* uri)
1702 TnyStream *result = NULL;
1704 GnomeVFSHandle *handle = NULL;
1705 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1706 if (test == GNOME_VFS_OK) {
1707 /* Create the tinymail stream: */
1708 /* Presumably tinymai will call gnome_vfs_close (handle) later. */
1709 result = TNY_STREAM (tny_vfs_stream_new (handle));
1716 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1719 ModestMsgEditWindowPrivate *priv;
1720 GtkWidget *dialog = NULL;
1722 GSList *uris = NULL;
1723 GSList *uri_node = NULL;
1725 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1727 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1728 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1729 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1731 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1733 response = gtk_dialog_run (GTK_DIALOG (dialog));
1735 case GTK_RESPONSE_OK:
1736 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1741 gtk_widget_destroy (dialog);
1743 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1745 GnomeVFSHandle *handle = NULL;
1746 GnomeVFSResult result;
1747 GtkTextIter position;
1748 GtkTextMark *insert_mark;
1750 uri = (const gchar *) uri_node->data;
1751 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1752 if (result == GNOME_VFS_OK) {
1754 GnomeVFSFileInfo info;
1755 gchar *filename, *basename, *escaped_filename;
1756 TnyMimePart *mime_part;
1758 const gchar *mime_type = NULL;
1759 GnomeVFSURI *vfs_uri;
1761 vfs_uri = gnome_vfs_uri_new (uri);
1763 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1764 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1765 g_free (escaped_filename);
1766 gnome_vfs_uri_unref (vfs_uri);
1768 if (gnome_vfs_get_file_info (uri, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
1769 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1771 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1773 mime_part = tny_platform_factory_new_mime_part
1774 (modest_runtime_get_platform_factory ());
1776 TnyStream *stream = create_stream_for_uri (uri);
1777 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1779 content_id = g_strdup_printf ("%d", priv->last_cid);
1780 tny_mime_part_set_content_id (mime_part, content_id);
1781 g_free (content_id);
1784 basename = g_path_get_basename (filename);
1785 tny_mime_part_set_filename (mime_part, basename);
1788 pixbuf = pixbuf_from_stream (stream, mime_type);
1790 if (pixbuf != NULL) {
1791 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1792 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1793 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1796 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1797 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1799 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1800 gtk_widget_show_all (priv->attachments_caption);
1801 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1811 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
1814 ModestMsgEditWindowPrivate *priv;
1815 GtkWidget *dialog = NULL;
1817 GSList *uris = NULL;
1820 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1822 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1823 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
1824 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1826 response = gtk_dialog_run (GTK_DIALOG (dialog));
1828 case GTK_RESPONSE_OK:
1829 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1834 gtk_widget_destroy (dialog);
1836 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1837 const gchar *uri = (const gchar *) uri_node->data;
1838 modest_msg_edit_window_attach_file_one (window, uri);
1840 g_slist_foreach (uris, (GFunc) g_free, NULL);
1841 g_slist_free (uris);
1845 modest_msg_edit_window_attach_file_one (
1846 ModestMsgEditWindow *window,
1849 g_return_if_fail (window);
1850 g_return_if_fail (uri);
1852 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1855 GnomeVFSHandle *handle = NULL;
1856 GnomeVFSResult result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1857 if (result == GNOME_VFS_OK) {
1858 TnyMimePart *mime_part;
1860 const gchar *mime_type = NULL;
1862 gchar *escaped_filename;
1865 GnomeVFSFileInfo info;
1866 GnomeVFSURI *vfs_uri;
1868 vfs_uri = gnome_vfs_uri_new (uri);
1871 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1872 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1873 g_free (escaped_filename);
1874 gnome_vfs_uri_unref (vfs_uri);
1876 if (gnome_vfs_get_file_info (uri,
1878 GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
1879 GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1881 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1882 mime_part = tny_platform_factory_new_mime_part
1883 (modest_runtime_get_platform_factory ());
1884 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1886 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1888 content_id = g_strdup_printf ("%d", priv->last_cid);
1889 tny_mime_part_set_content_id (mime_part, content_id);
1890 g_free (content_id);
1893 basename = g_path_get_basename (filename);
1894 tny_mime_part_set_filename (mime_part, basename);
1897 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1898 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1900 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1901 gtk_widget_show_all (priv->attachments_caption);
1902 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1908 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1911 ModestMsgEditWindowPrivate *priv;
1912 gboolean clean_list = FALSE;
1914 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1915 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1917 if (att_list == NULL) {
1918 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1922 if (att_list == NULL) {
1923 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1925 GtkWidget *confirmation_dialog = NULL;
1926 gboolean dialog_response;
1928 gchar *message = NULL;
1929 const gchar *filename = NULL;
1931 if (att_list->next == NULL) {
1932 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1936 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1937 att_list->next == NULL), filename);
1938 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1940 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1941 gtk_widget_destroy (confirmation_dialog);
1942 if (!dialog_response) {
1944 g_list_free (att_list);
1947 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1949 for (node = att_list; node != NULL; node = g_list_next (node)) {
1950 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1951 const gchar *att_id;
1952 priv->attachments = g_list_remove (priv->attachments, mime_part);
1954 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1956 if (priv->attachments == NULL)
1957 gtk_widget_hide (priv->attachments_caption);
1958 att_id = tny_mime_part_get_content_id (mime_part);
1960 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1962 g_object_unref (mime_part);
1963 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1968 g_list_free (att_list);
1972 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1975 ModestMsgEditWindowPrivate *priv;
1976 GdkColor *new_color;
1977 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1979 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1980 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1983 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1985 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1987 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1989 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1994 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1997 ModestMsgEditWindowPrivate *priv;
1998 gint new_size_index;
1999 ModestMsgEditWindow *window;
2002 window = MODEST_MSG_EDIT_WINDOW (userdata);
2003 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2004 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2006 if (gtk_check_menu_item_get_active (menu_item)) {
2008 WPTextBufferFormat format;
2010 memset (&format, 0, sizeof (format));
2011 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2013 label = gtk_bin_get_child (GTK_BIN (menu_item));
2015 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2016 format.cs.font_size = TRUE;
2017 format.cs.text_position = TRUE;
2018 format.cs.font = TRUE;
2019 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2020 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2022 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2023 (gpointer) wp_get_font_size_index (new_size_index, 12)))
2024 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2026 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2027 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2028 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2034 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2037 ModestMsgEditWindowPrivate *priv;
2038 gint new_font_index;
2039 ModestMsgEditWindow *window;
2042 window = MODEST_MSG_EDIT_WINDOW (userdata);
2043 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2044 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2046 if (gtk_check_menu_item_get_active (menu_item)) {
2049 label = gtk_bin_get_child (GTK_BIN (menu_item));
2051 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2053 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2054 (gpointer) new_font_index))
2055 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2057 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2058 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2059 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2065 modest_msg_edit_window_set_zoom (ModestWindow *window,
2068 ModestMsgEditWindowPrivate *priv;
2069 ModestWindowPrivate *parent_priv;
2070 GtkRadioAction *zoom_radio_action;
2072 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2074 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2075 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2076 priv->zoom_level = zoom;
2077 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom*DEFAULT_FONT_SCALE);
2079 /* Zoom level menu options should be updated with the current zoom level */
2080 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2081 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2082 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2083 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2084 /* FIXME: Not availible before Gtk 2.10 */
2086 gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
2091 modest_msg_edit_window_get_zoom (ModestWindow *window)
2093 ModestMsgEditWindowPrivate *priv;
2095 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
2097 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2098 return priv->zoom_level;
2102 zoom_allowed (ModestMsgEditWindow *window)
2106 focus = gtk_window_get_focus (GTK_WINDOW (window));
2107 return (focus != NULL && WP_IS_TEXT_VIEW (focus));
2111 modest_msg_edit_window_zoom_plus (ModestWindow *window)
2113 ModestWindowPrivate *parent_priv;
2114 GtkRadioAction *zoom_radio_action;
2115 GSList *group, *node;
2117 /* First we check if the text view is focused. If not, zooming is not allowed */
2118 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2119 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2123 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2124 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2125 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2127 group = gtk_radio_action_get_group (zoom_radio_action);
2129 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
2130 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
2134 for (node = group; node != NULL; node = g_slist_next (node)) {
2135 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
2136 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
2144 modest_msg_edit_window_zoom_minus (ModestWindow *window)
2146 ModestWindowPrivate *parent_priv;
2147 GtkRadioAction *zoom_radio_action;
2148 GSList *group, *node;
2150 /* First we check if the text view is focused. If not, zooming is not allowed */
2151 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2152 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2156 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2157 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2158 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2160 group = gtk_radio_action_get_group (zoom_radio_action);
2162 for (node = group; node != NULL; node = g_slist_next (node)) {
2163 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
2164 if (node->next != NULL) {
2165 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
2168 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
2176 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2178 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2179 ModestWindowPrivate *parent_priv;
2180 ModestWindowMgr *mgr;
2181 gboolean is_fullscreen;
2182 GtkAction *fs_toggle_action;
2185 mgr = modest_runtime_get_window_mgr ();
2186 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2188 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2190 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2191 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2192 if (is_fullscreen != active)
2193 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2201 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2204 ModestMsgEditWindowPrivate *priv = NULL;
2205 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2207 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2208 if (!priv->update_caption_visibility)
2211 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2213 gtk_widget_show (priv->cc_caption);
2215 gtk_widget_hide (priv->cc_caption);
2217 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2221 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2224 ModestMsgEditWindowPrivate *priv = NULL;
2225 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2227 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2228 if (!priv->update_caption_visibility)
2231 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2233 gtk_widget_show (priv->bcc_caption);
2235 gtk_widget_hide (priv->bcc_caption);
2237 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2241 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2242 ModestRecptEditor *editor)
2244 ModestMsgEditWindowPrivate *priv;
2246 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2247 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2248 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2250 if (editor == NULL) {
2251 GtkWidget *view_focus;
2252 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2254 /* This code should be kept in sync with ModestRecptEditor. The
2255 textview inside the recpt editor is the one that really gets the
2256 focus. As it's inside a scrolled window, and this one inside the
2257 hbox recpt editor inherits from, we'll need to go up in the
2258 hierarchy to know if the text view is part of the recpt editor
2259 or if it's a different text entry */
2261 if (gtk_widget_get_parent (view_focus)) {
2262 GtkWidget *first_parent;
2264 first_parent = gtk_widget_get_parent (view_focus);
2265 if (gtk_widget_get_parent (first_parent) &&
2266 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2267 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2272 editor = MODEST_RECPT_EDITOR (priv->to_field);
2276 modest_address_book_select_addresses (editor);
2281 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2283 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2285 modest_msg_edit_window_open_addressbook (window, NULL);
2289 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2290 gboolean show_toolbar)
2292 ModestWindowPrivate *parent_priv;
2293 const gchar *action_name;
2296 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2297 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2299 /* We can not just use the code of
2300 modest_msg_edit_window_setup_toolbar because it has a
2301 mixture of both initialization and creation code. */
2303 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2305 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2307 /* Update also the actions (to update the toggles in the
2308 menus), we have to do it manually because some other window
2309 of the same time could have changed it (remember that the
2310 toolbar fullscreen mode is shared by all the windows of the
2312 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2313 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2315 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2317 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2318 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2324 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2325 TnyHeaderFlags priority_flags)
2327 ModestMsgEditWindowPrivate *priv;
2328 ModestWindowPrivate *parent_priv;
2330 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2332 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2333 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2334 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2336 if (priv->priority_flags != priority_flags) {
2337 GtkAction *priority_action = NULL;
2339 priv->priority_flags = priority_flags;
2341 switch (priority_flags) {
2342 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2343 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2344 gtk_widget_show (priv->priority_icon);
2345 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2346 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2348 case TNY_HEADER_FLAG_LOW_PRIORITY:
2349 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2350 gtk_widget_show (priv->priority_icon);
2351 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2352 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2355 gtk_widget_hide (priv->priority_icon);
2356 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2357 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2360 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2361 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2366 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2369 ModestMsgEditWindowPrivate *priv;
2370 ModestWindowPrivate *parent_priv;
2371 gint current_format;
2373 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2375 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2376 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2378 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2379 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2381 if (current_format != file_format) {
2382 switch (file_format) {
2383 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2384 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2386 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2390 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2391 response = gtk_dialog_run (GTK_DIALOG (dialog));
2392 gtk_widget_destroy (dialog);
2393 if (response == GTK_RESPONSE_OK) {
2394 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2396 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2397 modest_maemo_toggle_action_set_active_block_notify (action, TRUE);
2402 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2407 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2410 ModestMsgEditWindowPrivate *priv;
2411 WPTextBufferFormat oldfmt, fmt;
2412 gint old_position = 0;
2416 GdkColor *color = NULL;
2417 gboolean bold, bold_set, italic, italic_set;
2418 gboolean underline, underline_set;
2419 gboolean strikethrough, strikethrough_set;
2420 gboolean position_set;
2421 gboolean font_size_set, font_set, color_set;
2424 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2425 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2427 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2429 /* First we get the currently selected font information */
2430 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2431 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2433 switch (oldfmt.text_position) {
2434 case TEXT_POSITION_NORMAL:
2437 case TEXT_POSITION_SUPERSCRIPT:
2445 g_object_set (G_OBJECT (dialog),
2446 "bold", oldfmt.bold != FALSE,
2447 "bold-set", !oldfmt.cs.bold,
2448 "underline", oldfmt.underline != FALSE,
2449 "underline-set", !oldfmt.cs.underline,
2450 "italic", oldfmt.italic != FALSE,
2451 "italic-set", !oldfmt.cs.italic,
2452 "strikethrough", oldfmt.strikethrough != FALSE,
2453 "strikethrough-set", !oldfmt.cs.strikethrough,
2454 "color", &oldfmt.color,
2455 "color-set", !oldfmt.cs.color,
2456 "size", wp_font_size[oldfmt.font_size],
2457 "size-set", !oldfmt.cs.font_size,
2458 "position", old_position,
2459 "position-set", !oldfmt.cs.text_position,
2460 "family", wp_get_font_name (oldfmt.font),
2461 "family-set", !oldfmt.cs.font,
2464 gtk_widget_show_all (dialog);
2465 response = gtk_dialog_run (GTK_DIALOG (dialog));
2466 if (response == GTK_RESPONSE_OK) {
2468 g_object_get( dialog,
2470 "bold-set", &bold_set,
2471 "underline", &underline,
2472 "underline-set", &underline_set,
2474 "italic-set", &italic_set,
2475 "strikethrough", &strikethrough,
2476 "strikethrough-set", &strikethrough_set,
2478 "color-set", &color_set,
2480 "size-set", &font_size_set,
2481 "family", &font_name,
2482 "family-set", &font_set,
2483 "position", &position,
2484 "position-set", &position_set,
2489 if (response == GTK_RESPONSE_OK) {
2490 memset(&fmt, 0, sizeof(fmt));
2496 fmt.italic = italic;
2497 fmt.cs.italic = TRUE;
2499 if (underline_set) {
2500 fmt.underline = underline;
2501 fmt.cs.underline = TRUE;
2503 if (strikethrough_set) {
2504 fmt.strikethrough = strikethrough;
2505 fmt.cs.strikethrough = TRUE;
2510 ? TEXT_POSITION_NORMAL
2511 : ( ( position == 1 )
2512 ? TEXT_POSITION_SUPERSCRIPT
2513 : TEXT_POSITION_SUBSCRIPT );
2514 fmt.cs.text_position = TRUE;
2518 fmt.cs.color = TRUE;
2521 fmt.font = wp_get_font_index(font_name,
2526 if (font_size_set) {
2527 fmt.font_size = wp_get_font_size_index(
2528 font_size, DEFAULT_FONT_SIZE);
2529 fmt.cs.font_size = TRUE;
2531 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2533 gtk_widget_destroy (dialog);
2535 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2539 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2541 ModestMsgEditWindowPrivate *priv;
2543 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2544 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2546 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2548 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2553 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2555 ModestMsgEditWindowPrivate *priv;
2557 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2558 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2560 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2562 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2567 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2569 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2571 priv->can_undo = can_undo;
2575 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2577 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2579 priv->can_redo = can_redo;
2583 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2585 ModestMsgEditWindowPrivate *priv;
2586 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2587 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2589 return priv->can_undo;
2593 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2595 ModestMsgEditWindowPrivate *priv;
2596 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2597 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2599 return priv->can_redo;
2604 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2607 GtkTextIter match_start, match_end;
2609 if (image_id == NULL)
2612 gtk_text_buffer_get_start_iter (buffer, &iter);
2614 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2615 GSList *tags = gtk_text_iter_get_tags (&match_start);
2617 for (node = tags; node != NULL; node = g_slist_next (node)) {
2618 GtkTextTag *tag = (GtkTextTag *) node->data;
2619 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2620 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2621 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2623 offset = gtk_text_iter_get_offset (&match_start);
2624 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2625 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2629 gtk_text_iter_forward_char (&iter);
2634 message_is_empty (ModestMsgEditWindow *window)
2636 ModestMsgEditWindowPrivate *priv = NULL;
2638 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2639 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2641 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
2642 * so we can ignore markup.
2644 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
2647 count = gtk_text_buffer_get_char_count (buf);
2653 msg_body_focus (GtkWidget *focus,
2654 GdkEventFocus *event,
2658 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
2663 recpt_field_changed (GtkTextBuffer *buffer,
2664 ModestMsgEditWindow *editor)
2666 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
2670 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
2672 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
2676 reset_modified (ModestMsgEditWindow *editor)
2678 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2679 GtkTextBuffer *buffer;
2681 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2682 gtk_text_buffer_set_modified (buffer, FALSE);
2683 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2684 gtk_text_buffer_set_modified (buffer, FALSE);
2685 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2686 gtk_text_buffer_set_modified (buffer, FALSE);
2687 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2691 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2693 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2694 GtkTextBuffer *buffer;
2696 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2697 if (gtk_text_buffer_get_modified (buffer))
2699 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2700 if (gtk_text_buffer_get_modified (buffer))
2702 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2703 if (gtk_text_buffer_get_modified (buffer))
2705 if (gtk_text_buffer_get_modified (priv->text_buffer))
2715 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
2717 ModestMsgEditWindowPrivate *priv = NULL;
2719 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2720 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2722 /* check if there's no recipient added */
2723 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2724 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2725 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2726 /* no recipient contents, then select contacts */
2727 modest_msg_edit_window_open_addressbook (window, NULL);
2731 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
2732 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2735 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
2736 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
2739 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
2740 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
2744 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
2745 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
2746 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2753 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2754 ModestMsgEditWindow *window)
2756 modest_msg_edit_window_offer_attach_file (window);
2760 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2762 ModestMsgEditWindow *window)
2764 if (!GTK_WIDGET_VISIBLE (window))
2767 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), "ModestClipboardDimmingRules");
2770 subject_field_move_cursor (GtkEntry *entry,
2771 GtkMovementStep step,
2776 if (!GTK_WIDGET_VISIBLE (window))
2779 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), "ModestClipboardDimmingRules");
2783 update_window_title (ModestMsgEditWindow *window)
2785 ModestMsgEditWindowPrivate *priv = NULL;
2786 const gchar *subject;
2788 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2789 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2790 if (subject == NULL || subject[0] == '\0')
2791 subject = _("mail_va_new_email");
2793 gtk_window_set_title (GTK_WINDOW (window), subject);
2798 subject_field_changed (GtkEditable *editable,
2799 ModestMsgEditWindow *window)
2801 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2802 update_window_title (window);
2803 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2804 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2808 subject_field_insert_text (GtkEditable *editable,
2810 gint new_text_length,
2812 ModestMsgEditWindow *window)
2814 GString *result = g_string_new ("");
2816 gint result_len = 0;
2818 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
2819 gunichar c = g_utf8_get_char_validated (current, 8);
2820 /* Invalid unichar, stop */
2826 result = g_string_append_unichar (result, c);
2830 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
2831 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
2834 /* Prevent endless recursion */
2835 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
2836 g_signal_emit_by_name (editable, "insert-text",
2837 (gpointer) result->str, (gpointer) result->len,
2838 (gpointer) position, (gpointer) window);
2839 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
2843 g_string_free (result, TRUE);
2847 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2850 ModestMsgEditWindowPrivate *priv = NULL;
2852 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2853 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2855 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2858 gtk_widget_show_all (priv->find_toolbar);
2859 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2861 gtk_widget_hide_all (priv->find_toolbar);
2862 gtk_widget_grab_focus (priv->msg_body);
2868 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2870 GtkTextIter *match_start,
2871 GtkTextIter *match_end)
2873 GtkTextIter end_iter;
2874 gchar *str_casefold;
2877 gchar *range_casefold;
2880 gboolean result = FALSE;
2887 gtk_text_iter_forward_to_end (&end_iter);
2889 str_casefold = g_utf8_casefold (str, -1);
2890 str_chars_n = strlen (str);
2892 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2893 range_casefold = g_utf8_casefold (range_text, -1);
2894 range_chars_n = strlen (range_casefold);
2896 if (range_chars_n < str_chars_n) {
2897 g_free (str_casefold);
2898 g_free (range_text);
2899 g_free (range_casefold);
2903 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2904 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2905 if (!g_utf8_collate (range_subtext, str_casefold)) {
2906 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2908 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2909 match_start, match_end, NULL);
2910 g_free (found_text);
2912 g_free (range_subtext);
2916 g_free (str_casefold);
2917 g_free (range_text);
2918 g_free (range_casefold);
2925 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2926 ModestMsgEditWindow *window)
2928 gchar *current_search = NULL;
2929 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2931 GtkTextIter selection_start, selection_end;
2932 GtkTextIter match_start, match_end;
2933 gboolean continue_search = FALSE;
2935 if (message_is_empty (window)) {
2936 g_free (priv->last_search);
2937 priv->last_search = NULL;
2938 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
2942 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2943 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2944 g_free (current_search);
2945 g_free (priv->last_search);
2946 priv->last_search = NULL;
2947 /* Information banner about empty search */
2948 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2952 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2953 continue_search = TRUE;
2955 g_free (priv->last_search);
2956 priv->last_search = g_strdup (current_search);
2959 if (continue_search) {
2960 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2961 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2962 &match_start, &match_end);
2964 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2966 GtkTextIter buffer_start;
2967 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2968 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2969 &match_start, &match_end);
2971 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2974 /* Mark as selected the string found in search */
2976 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2977 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2979 g_free (priv->last_search);
2980 priv->last_search = NULL;
2982 g_free (current_search);
2986 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2987 ModestMsgEditWindow *window)
2989 GtkToggleAction *toggle;
2990 ModestWindowPrivate *parent_priv;
2991 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2993 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2994 gtk_toggle_action_set_active (toggle, FALSE);
2998 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3000 ModestMsgEditWindowPrivate *priv;
3002 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3007 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3010 ModestMsgEditWindowPrivate *priv;
3012 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3018 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3021 ModestMsgEditWindowPrivate *priv;
3022 TnyHeader *header = NULL;
3024 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3025 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3027 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3028 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3030 if (priv->draft_msg != NULL) {
3031 header = tny_msg_get_header (priv->draft_msg);
3032 if (TNY_IS_HEADER (header)) {
3033 modest_window_mgr_unregister_header (mgr, header);
3035 g_object_unref (priv->draft_msg);
3038 if (draft != NULL) {
3039 g_object_ref (draft);
3040 header = tny_msg_get_header (draft);
3041 if (TNY_IS_HEADER (header))
3042 modest_window_mgr_register_header (mgr, header);
3043 if (priv->msg_uid) {
3044 g_free (priv->msg_uid);
3045 priv->msg_uid = NULL;
3047 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3050 priv->draft_msg = draft;
3054 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3055 GtkTextIter *start, GtkTextIter *end,
3058 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3059 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3062 if (tag == NULL+13) return;
3063 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3064 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3065 replace_with_attachments (window, priv->attachments);
3070 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3073 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3075 g_return_if_fail (TNY_IS_MIME_PART (part));
3076 priv->attachments = g_list_prepend (priv->attachments, part);
3077 g_object_ref (part);
3078 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part);
3079 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3080 gtk_widget_show_all (priv->attachments_caption);
3081 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3085 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3087 ModestMsgEditWindowPrivate *priv;
3089 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3090 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3092 return priv->msg_uid;
3096 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3097 ModestMsgEditWindowWidgetType widget_type)
3099 ModestMsgEditWindowPrivate *priv;
3101 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3102 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3104 switch (widget_type) {
3105 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3106 return priv->msg_body;
3108 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3109 return priv->to_field;
3111 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3112 return priv->cc_field;
3114 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3115 return priv->bcc_field;
3117 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3118 return priv->subject_field;
3120 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3121 return priv->attachments_view;