1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
41 #include <modest-account-mgr.h>
42 #include <modest-account-mgr-helpers.h>
44 #include <widgets/modest-msg-edit-window.h>
45 #include <widgets/modest-combo-box.h>
46 #include <widgets/modest-recpt-editor.h>
47 #include <widgets/modest-attachments-view.h>
49 #include <modest-runtime.h>
51 #include "modest-platform.h"
52 #include "modest-icon-names.h"
53 #include "modest-widget-memory.h"
54 #include "modest-window-priv.h"
55 #include "modest-mail-operation.h"
56 #include "modest-tny-platform-factory.h"
57 #include "modest-tny-msg.h"
58 #include "modest-tny-folder.h"
59 #include "modest-address-book.h"
60 #include "modest-text-utils.h"
61 #include <tny-simple-list.h>
62 #include <wptextview.h>
63 #include <wptextbuffer.h>
64 #include "modest-scroll-area.h"
66 #include "modest-hildon-includes.h"
67 #ifdef MODEST_HAVE_HILDON0_WIDGETS
68 #include <hildon-widgets/hildon-color-chooser.h>
70 #include "widgets/modest-msg-edit-window-ui.h"
71 #ifdef MODEST_HAVE_HILDON0_WIDGETS
72 #include <libgnomevfs/gnome-vfs-mime-utils.h>
74 #include <libgnomevfs/gnome-vfs-mime.h>
76 #include "modest-maemo-utils.h"
79 #define DEFAULT_FONT_SIZE 3
80 #define DEFAULT_FONT 2
81 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
82 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
83 #define DEFAULT_MAIN_VBOX_SPACING 6
84 #define SUBJECT_MAX_LENGTH 1000
85 #define IMAGE_MAX_WIDTH 560
86 #define DEFAULT_FONT_SCALE 1.5
88 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
89 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
90 static void modest_msg_edit_window_finalize (GObject *obj);
92 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
93 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
94 static void send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
95 static void style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
96 static void setup_insensitive_handlers (ModestMsgEditWindow *editor);
97 static void reset_modified (ModestMsgEditWindow *editor);
99 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
100 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
101 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
102 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
103 GtkTextIter *start, GtkTextIter *end,
105 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
106 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
107 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
109 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
111 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
113 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
114 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
115 GdkEventWindowState *event,
117 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
118 ModestRecptEditor *editor);
119 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
120 ModestMsgEditWindow *window);
122 /* ModestWindow methods implementation */
123 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
124 static void modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom);
125 static gdouble modest_msg_edit_window_get_zoom (ModestWindow *window);
126 static gboolean modest_msg_edit_window_zoom_minus (ModestWindow *window);
127 static gboolean modest_msg_edit_window_zoom_plus (ModestWindow *window);
128 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
129 gboolean show_toolbar);
130 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
132 ModestMsgEditWindow *window);
133 static void update_window_title (ModestMsgEditWindow *window);
134 static void update_dimmed (ModestMsgEditWindow *window);
135 static void update_paste_dimming (ModestMsgEditWindow *window);
136 static void update_select_all_dimming (ModestMsgEditWindow *window);
137 static void update_zoom_dimming (ModestMsgEditWindow *window);
140 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
141 ModestMsgEditWindow *window);
142 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
143 ModestMsgEditWindow *window);
144 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
146 GtkTextIter *match_start,
147 GtkTextIter *match_end);
149 static void DEBUG_BUFFER (WPTextBuffer *buffer)
154 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
155 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
156 while (!gtk_text_iter_is_end (&iter)) {
157 GString *output = g_string_new ("");
158 GSList *toggled_tags;
161 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
162 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
163 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
164 GtkTextTag *tag = (GtkTextTag *) node->data;
166 g_object_get (G_OBJECT (tag), "name", &name, NULL);
167 output = g_string_append (output, name);
168 g_string_append (output, " ");
170 output = g_string_append (output, "] OPENED [ ");
171 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
172 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
173 GtkTextTag *tag = (GtkTextTag *) node->data;
175 g_object_get (G_OBJECT (tag), "name", &name, NULL);
176 output = g_string_append (output, name);
177 g_string_append (output, " ");
179 output = g_string_append (output, "]\n");
180 g_message ("%s", output->str);
181 g_string_free (output, TRUE);
182 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
184 g_message ("END BUFFER");
189 /* static gboolean */
190 /* on_key_pressed (GtkWidget *self, */
191 /* GdkEventKey *event, */
192 /* gpointer user_data); */
194 static void edit_menu_activated (GtkAction *action,
196 static void view_menu_activated (GtkAction *action,
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 gulong clipboard_change_handler_id;
258 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
259 MODEST_TYPE_MSG_EDIT_WINDOW, \
260 ModestMsgEditWindowPrivate))
262 static GtkWindowClass *parent_class = NULL;
264 /* uncomment the following if you have defined any signals */
265 /* static guint signals[LAST_SIGNAL] = {0}; */
268 modest_msg_edit_window_get_type (void)
270 static GType my_type = 0;
272 static const GTypeInfo my_info = {
273 sizeof(ModestMsgEditWindowClass),
274 NULL, /* base init */
275 NULL, /* base finalize */
276 (GClassInitFunc) modest_msg_edit_window_class_init,
277 NULL, /* class finalize */
278 NULL, /* class data */
279 sizeof(ModestMsgEditWindow),
281 (GInstanceInitFunc) modest_msg_edit_window_init,
284 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
285 "ModestMsgEditWindow",
288 wp_text_buffer_library_init ();
294 save_state (ModestWindow *self)
296 modest_widget_memory_save (modest_runtime_get_conf(),
297 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
302 restore_settings (ModestMsgEditWindow *self)
304 modest_widget_memory_restore (modest_runtime_get_conf(),
305 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
310 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
312 GObjectClass *gobject_class;
313 ModestWindowClass *modest_window_class;
314 gobject_class = (GObjectClass*) klass;
315 modest_window_class = (ModestWindowClass*) klass;
317 parent_class = g_type_class_peek_parent (klass);
318 gobject_class->finalize = modest_msg_edit_window_finalize;
320 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
321 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
322 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
323 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
324 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
325 modest_window_class->save_state_func = save_state;
326 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
328 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
332 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
334 ModestMsgEditWindowPrivate *priv;
335 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
337 priv->msg_body = NULL;
338 priv->from_field = NULL;
339 priv->to_field = NULL;
340 priv->cc_field = NULL;
341 priv->bcc_field = NULL;
342 priv->subject_field = NULL;
343 priv->attachments = NULL;
345 priv->zoom_level = 1.0;
347 priv->cc_caption = NULL;
348 priv->bcc_caption = NULL;
349 priv->update_caption_visibility = FALSE;
351 priv->priority_flags = 0;
353 priv->find_toolbar = NULL;
354 priv->last_search = NULL;
356 priv->draft_msg = NULL;
357 priv->outbox_msg = NULL;
358 priv->clipboard_change_handler_id = 0;
361 priv->last_vadj_upper = 0;
365 /* FIXME: this is a dup from the one in gtk/ */
368 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
370 static ModestPairList*
371 get_transports (void)
373 GSList *transports = NULL;
375 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
376 GSList *accounts = modest_account_mgr_account_names (account_mgr,
377 TRUE /* only enabled accounts. */);
379 GSList *cursor = accounts;
381 gchar *account_name = cursor->data;
382 gchar *from_string = NULL;
384 from_string = modest_account_mgr_get_from_string (account_mgr,
388 if (from_string && account_name) {
389 gchar *name = account_name;
390 ModestPair *pair = modest_pair_new ((gpointer) name,
391 (gpointer) from_string , TRUE);
392 transports = g_slist_prepend (transports, pair);
395 cursor = cursor->next;
397 g_slist_free (accounts); /* only free the accounts, not the elements,
398 * because they are used in the pairlist */
402 void vadj_changed (GtkAdjustment *adj,
403 ModestMsgEditWindow *window)
405 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
407 GdkRectangle rectangle, cursor_rectangle;
408 GtkTextIter position;
412 /* We detect if cursor is visible using the full height, not only the center. This
414 gtk_text_view_get_visible_rect (GTK_TEXT_VIEW (priv->msg_body), &rectangle);
415 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer),
417 gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer)));
418 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &position, &cursor_rectangle);
420 cursor_bottom = (cursor_rectangle.y + cursor_rectangle.height);
421 visible = (cursor_rectangle.y >= rectangle.y) && (cursor_bottom < (rectangle.y + rectangle.height));
423 if (gtk_widget_is_focus (priv->msg_body) &&
425 if (priv->last_vadj_upper != adj->upper) {
428 insert = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
429 gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (priv->msg_body),
430 insert, 0.1, FALSE, 0.0, 0.0);
433 priv->last_vadj_upper = adj->upper;
438 init_window (ModestMsgEditWindow *obj)
440 GtkWidget *from_caption, *to_caption, *subject_caption;
441 GtkWidget *main_vbox;
442 ModestMsgEditWindowPrivate *priv;
444 GtkSizeGroup *size_group;
446 GtkWidget *subject_box;
447 GtkWidget *attachment_icon;
448 GtkWidget *window_box;
449 #if (GTK_MINOR_VERSION >= 10)
450 GdkAtom deserialize_type;
452 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
454 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
456 /* Note: This ModestPairList* must exist for as long as the combo
457 * that uses it, because the ModestComboBox uses the ID opaquely,
458 * so it can't know how to manage its memory. */
459 priv->from_field_protos = get_transports ();
461 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
463 priv->to_field = modest_recpt_editor_new ();
464 priv->cc_field = modest_recpt_editor_new ();
465 priv->bcc_field = modest_recpt_editor_new ();
466 subject_box = gtk_hbox_new (FALSE, 0);
467 priv->priority_icon = gtk_image_new ();
468 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
469 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
470 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
471 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
472 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
473 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
474 priv->add_attachment_button = gtk_button_new ();
475 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
476 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
477 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
478 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
479 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
480 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
481 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
482 priv->attachments_view = modest_attachments_view_new (NULL);
484 priv->header_box = gtk_vbox_new (FALSE, 0);
486 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
487 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
488 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
489 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
490 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
491 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
492 g_object_unref (size_group);
494 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
495 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
496 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
497 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
498 gtk_size_group_add_widget (size_group, priv->subject_field);
499 gtk_size_group_add_widget (size_group, priv->attachments_view);
500 g_object_unref (size_group);
502 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
503 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
504 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
505 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
506 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
507 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
508 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
511 priv->msg_body = wp_text_view_new ();
512 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
513 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
514 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
515 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
516 #if (GTK_MINOR_VERSION >= 10)
517 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
518 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
520 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
521 deserialize_type, TRUE);
523 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
525 priv->find_toolbar = hildon_find_toolbar_new (NULL);
526 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
528 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
530 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
531 G_CALLBACK (text_buffer_refresh_attributes), obj);
532 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
533 G_CALLBACK (text_buffer_can_undo), obj);
534 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
535 G_CALLBACK (text_buffer_can_redo), obj);
536 g_signal_connect (G_OBJECT (obj), "window-state-event",
537 G_CALLBACK (modest_msg_edit_window_window_state_event),
539 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
540 G_CALLBACK (text_buffer_apply_tag), obj);
541 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
542 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
543 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
544 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
545 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
546 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
548 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
549 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
551 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
552 G_CALLBACK (msg_body_focus), obj);
553 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
554 G_CALLBACK (msg_body_focus), obj);
555 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
556 "changed", G_CALLBACK (recpt_field_changed), obj);
557 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
558 "changed", G_CALLBACK (recpt_field_changed), obj);
559 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
560 "changed", G_CALLBACK (recpt_field_changed), obj);
561 recpt_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
562 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
564 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
565 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
567 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
568 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
569 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
570 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
572 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
574 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
575 frame = gtk_frame_new (NULL);
576 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
578 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
579 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
580 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
582 G_CALLBACK (vadj_changed),
584 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
586 window_box = gtk_vbox_new (FALSE, 0);
587 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
588 gtk_container_add (GTK_CONTAINER(obj), window_box);
589 priv->scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
590 gtk_container_add (GTK_CONTAINER (frame), priv->scroll_area);
592 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
593 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
598 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
600 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
602 if (g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
603 priv->clipboard_change_handler_id))
604 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
605 priv->clipboard_change_handler_id);
609 modest_msg_edit_window_finalize (GObject *obj)
611 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
613 /* Sanity check: shouldn't be needed, the window mgr should
614 call this function before */
615 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
617 if (priv->draft_msg != NULL) {
618 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
619 if (TNY_IS_HEADER (header)) {
620 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
621 modest_window_mgr_unregister_header (mgr, header);
623 g_object_unref (priv->draft_msg);
624 priv->draft_msg = NULL;
626 if (priv->outbox_msg != NULL) {
627 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
628 if (TNY_IS_HEADER (header)) {
629 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
630 modest_window_mgr_unregister_header (mgr, header);
632 g_object_unref (priv->outbox_msg);
633 priv->outbox_msg = NULL;
636 /* This had to stay alive for as long as the combobox that used it: */
637 modest_pair_list_free (priv->from_field_protos);
639 G_OBJECT_CLASS(parent_class)->finalize (obj);
643 menubar_to_menu (GtkUIManager *ui_manager)
645 GtkWidget *main_menu;
649 /* Create new main menu */
650 main_menu = gtk_menu_new();
652 /* Get the menubar from the UI manager */
653 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
655 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
659 menu = GTK_WIDGET (iter->data);
660 gtk_widget_reparent(menu, main_menu);
662 iter = g_list_next (iter);
668 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type)
670 GdkPixbufLoader *loader;
673 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
678 tny_stream_reset (TNY_STREAM (stream));
679 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
680 unsigned char read_buffer[128];
682 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
683 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
687 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
688 g_object_ref (pixbuf);
689 gdk_pixbuf_loader_close (loader, NULL);
690 g_object_unref (loader);
692 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
693 GdkPixbuf *new_pixbuf;
695 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
696 gdk_pixbuf_get_width (pixbuf);
697 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
698 g_object_unref (pixbuf);
706 replace_with_attachments (ModestMsgEditWindow *self, GList *attachments)
708 ModestMsgEditWindowPrivate *priv;
711 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
713 for (node = attachments; node != NULL; node = g_list_next (node)) {
714 TnyMimePart *part = (TnyMimePart *) node->data;
715 const gchar *cid = tny_mime_part_get_content_id (part);
716 const gchar *mime_type = tny_mime_part_get_content_type (part);
717 if ((cid != NULL)&&(mime_type != NULL)) {
718 TnyStream *stream = tny_mime_part_get_stream (part);
719 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type);
720 g_object_unref (stream);
722 if (pixbuf != NULL) {
723 /* wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf); */
724 g_object_unref (pixbuf);
731 update_last_cid (ModestMsgEditWindow *self, GList *attachments)
734 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
736 for (node = attachments; node != NULL; node = g_list_next (node)) {
737 TnyMimePart *part = (TnyMimePart *) node->data;
738 const gchar *cid = tny_mime_part_get_content_id (part);
740 char *invalid = NULL;
741 gint int_cid = strtol (cid, &invalid, 10);
742 if ((invalid != NULL) && (*invalid == '\0') && (int_cid > priv->last_cid)) {
743 priv->last_cid = int_cid;
751 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
754 const gchar *to, *cc, *bcc, *subject;
756 ModestMsgEditWindowPrivate *priv;
758 TnyHeaderFlags priority_flags;
759 TnyFolder *msg_folder;
760 gboolean is_html = FALSE;
762 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
763 g_return_if_fail (TNY_IS_MSG (msg));
765 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
767 header = tny_msg_get_header (msg);
768 to = tny_header_get_to (header);
769 cc = tny_header_get_cc (header);
770 bcc = tny_header_get_bcc (header);
771 subject = tny_header_get_subject (header);
772 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
775 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
777 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
778 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
779 gtk_widget_show (priv->cc_caption);
780 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
781 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
782 gtk_widget_hide (priv->cc_caption);
785 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
786 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
787 gtk_widget_show (priv->bcc_caption);
788 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
789 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
790 gtk_widget_hide (priv->bcc_caption);
793 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
794 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
797 update_window_title (self);
799 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
800 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
802 if ((body == NULL)||(body[0] == '\0')) {
804 body = modest_text_utils_convert_to_html ("");
807 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
808 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
811 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
814 if (preserve_is_rich && !is_html) {
815 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
816 /* Get the default format required from configuration */
817 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
818 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
821 /* Set the default focus depending on having already a To: field or not */
822 if ((!to)||(*to == '\0')) {
823 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
825 gtk_widget_grab_focus (priv->msg_body);
828 /* TODO: lower priority, select in the From: combo to the
829 value that comes from msg <- not sure, should it be
832 /* Add attachments to the view */
833 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
834 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
835 if (priv->attachments == NULL) {
836 gtk_widget_hide (priv->attachments_caption);
838 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
839 gtk_widget_show_all (priv->attachments_caption);
840 replace_with_attachments (self, priv->attachments);
842 update_last_cid (self, priv->attachments);
844 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
846 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
847 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
849 reset_modified (self);
851 update_dimmed (self);
852 text_buffer_can_undo (priv->text_buffer, FALSE, self);
853 text_buffer_can_redo (priv->text_buffer, FALSE, self);
855 /* we should set a reference to the incoming message if it is a draft */
856 msg_folder = tny_msg_get_folder (msg);
858 if (modest_tny_folder_is_local_folder (msg_folder)) {
859 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
860 if (type == TNY_FOLDER_TYPE_DRAFTS)
861 priv->draft_msg = g_object_ref(msg);
862 if (type == TNY_FOLDER_TYPE_OUTBOX)
863 priv->outbox_msg = g_object_ref(msg);
865 g_object_unref (msg_folder);
870 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
873 GList *item_children, *node;
874 GtkWidget *bin_child;
876 bin_child = gtk_bin_get_child (GTK_BIN(item));
878 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
880 for (node = item_children; node != NULL; node = g_list_next (node)) {
881 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
882 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
885 g_list_free (item_children);
889 menu_tool_button_dont_expand (GtkMenuToolButton *item)
892 GList *item_children, *node;
894 box = gtk_bin_get_child (GTK_BIN (item));
895 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
896 item_children = gtk_container_get_children (GTK_CONTAINER (box));
898 for (node = item_children; node != NULL; node = g_list_next (node)) {
899 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
900 if (GTK_IS_TOGGLE_BUTTON (node->data))
901 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
902 else if (GTK_IS_BUTTON (node->data))
903 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
905 g_list_free (item_children);
910 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
912 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
913 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
914 GtkWidget *placeholder;
915 GtkWidget *tool_item;
920 GtkWidget *sizes_menu;
921 GtkWidget *fonts_menu;
922 GSList *radio_group = NULL;
927 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
928 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
930 /* should we hide the toolbar? */
931 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
932 gtk_widget_hide (parent_priv->toolbar);
934 /* Font color placeholder */
935 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
936 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
939 tool_item = GTK_WIDGET (gtk_tool_item_new ());
940 priv->font_color_button = hildon_color_button_new ();
941 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
942 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
943 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
944 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
945 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
946 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
947 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
949 /* Font size and face placeholder */
950 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
951 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
953 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
954 priv->size_tool_button_label = gtk_label_new (NULL);
955 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
956 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
957 size_text,"</span>", NULL);
958 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
960 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
961 sizes_menu = gtk_menu_new ();
962 priv->size_items_group = NULL;
964 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
965 GtkWidget *size_menu_item;
967 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
968 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
969 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
970 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
971 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
972 gtk_widget_show (size_menu_item);
974 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
978 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
979 GtkWidget *item = (GtkWidget *) node->data;
980 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
984 priv->size_items_group = g_slist_reverse (priv->size_items_group);
985 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
986 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
987 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
988 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
989 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
990 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
991 priv->font_size_toolitem = tool_item;
994 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
995 priv->font_tool_button_label = gtk_label_new (NULL);
996 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
997 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
999 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1000 fonts_menu = gtk_menu_new ();
1001 priv->font_items_group = NULL;
1003 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1004 GtkWidget *font_menu_item;
1005 GtkWidget *child_label;
1007 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1008 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1009 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1010 wp_get_font_name (font_index), "</span>", NULL);
1011 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1014 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1015 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1016 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1017 gtk_widget_show (font_menu_item);
1019 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1022 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1023 GtkWidget *item = (GtkWidget *) node->data;
1024 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1027 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1028 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1029 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1030 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1031 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1032 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1033 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1034 priv->font_face_toolitem = tool_item;
1036 /* Set expand and homogeneous for remaining items */
1037 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1038 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1039 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1040 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1041 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1042 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1043 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1044 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1045 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1053 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1056 ModestWindowPrivate *parent_priv;
1057 ModestMsgEditWindowPrivate *priv;
1058 GtkActionGroup *action_group;
1059 GError *error = NULL;
1060 GdkPixbuf *window_icon = NULL;
1063 gboolean prefer_formatted;
1065 ModestPair *account_pair = NULL;
1067 g_return_val_if_fail (msg, NULL);
1068 g_return_val_if_fail (account_name, NULL);
1070 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
1072 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1073 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1075 parent_priv->ui_manager = gtk_ui_manager_new();
1076 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
1077 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1079 /* Add common actions */
1080 gtk_action_group_add_actions (action_group,
1081 modest_msg_edit_action_entries,
1082 G_N_ELEMENTS (modest_msg_edit_action_entries),
1084 gtk_action_group_add_toggle_actions (action_group,
1085 modest_msg_edit_toggle_action_entries,
1086 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
1088 gtk_action_group_add_radio_actions (action_group,
1089 modest_msg_edit_alignment_radio_action_entries,
1090 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
1092 G_CALLBACK (modest_ui_actions_on_change_justify),
1094 gtk_action_group_add_radio_actions (action_group,
1095 modest_msg_edit_zoom_action_entries,
1096 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
1098 G_CALLBACK (modest_ui_actions_on_change_zoom),
1100 gtk_action_group_add_radio_actions (action_group,
1101 modest_msg_edit_priority_action_entries,
1102 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
1104 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
1106 gtk_action_group_add_radio_actions (action_group,
1107 modest_msg_edit_file_format_action_entries,
1108 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
1109 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
1110 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
1112 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1113 g_object_unref (action_group);
1115 /* Load the UI definition */
1116 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
1118 if (error != NULL) {
1119 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
1120 g_clear_error (&error);
1123 /* Add accelerators */
1124 gtk_window_add_accel_group (GTK_WINDOW (obj),
1125 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1128 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
1129 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1132 init_window (MODEST_MSG_EDIT_WINDOW(obj));
1134 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1136 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1138 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1139 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1141 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
1143 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
1144 if (account_pair != NULL)
1145 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
1147 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1149 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1151 /* Set window icon */
1152 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
1154 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1155 g_object_unref (window_icon);
1158 /* Dim at start clipboard actions */
1159 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
1160 gtk_action_set_sensitive (action, FALSE);
1161 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
1162 gtk_action_set_sensitive (action, FALSE);
1163 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
1164 gtk_action_set_sensitive (action, FALSE);
1166 /* Update select all */
1167 update_select_all_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1168 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu");
1169 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (edit_menu_activated), obj);
1170 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu");
1171 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (view_menu_activated), obj);
1173 /* set initial state of cc and bcc */
1174 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
1175 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1176 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
1177 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
1178 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1179 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
1181 /* Setup the file format */
1182 conf = modest_runtime_get_conf ();
1183 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
1185 g_clear_error (&error);
1186 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
1188 file_format = (prefer_formatted) ?
1189 MODEST_FILE_FORMAT_FORMATTED_TEXT :
1190 MODEST_FILE_FORMAT_PLAIN_TEXT;
1191 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
1193 update_paste_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1194 priv->update_caption_visibility = TRUE;
1196 reset_modified (MODEST_MSG_EDIT_WINDOW (obj));
1198 return (ModestWindow*) obj;
1202 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1204 GString **string_buffer = (GString **) user_data;
1206 *string_buffer = g_string_append (*string_buffer, buffer);
1212 * @result: A new string which should be freed with g_free().
1215 get_formatted_data (ModestMsgEditWindow *edit_window)
1217 ModestMsgEditWindowPrivate *priv;
1218 GString *string_buffer = g_string_new ("");
1220 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1222 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1224 return g_string_free (string_buffer, FALSE);
1229 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1232 const gchar *account_name;
1233 ModestMsgEditWindowPrivate *priv;
1235 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1237 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1239 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1240 g_return_val_if_fail (account_name, NULL);
1243 /* don't free these (except from) */
1244 data = g_slice_new0 (MsgData);
1245 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1247 data->account_name = g_strdup (account_name);
1248 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1249 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1250 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1251 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1252 if (priv->draft_msg) {
1253 data->draft_msg = g_object_ref (priv->draft_msg);
1255 if (priv->outbox_msg) {
1256 data->draft_msg = g_object_ref (priv->outbox_msg);
1258 data->draft_msg = NULL;
1261 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1263 gtk_text_buffer_get_bounds (buf, &b, &e);
1264 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1266 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1267 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1269 data->html_body = NULL;
1271 /* deep-copy the data */
1272 GList *cursor = priv->attachments;
1273 data->attachments = NULL;
1275 if (!(TNY_IS_MIME_PART(cursor->data))) {
1276 g_warning ("strange data in attachment list");
1277 cursor = g_list_next (cursor);
1280 data->attachments = g_list_append (data->attachments,
1281 g_object_ref (cursor->data));
1282 cursor = g_list_next (cursor);
1285 data->priority_flags = priv->priority_flags;
1292 unref_gobject (GObject *obj, gpointer data)
1294 if (!G_IS_OBJECT(obj))
1296 g_object_unref (obj);
1300 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1303 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1311 g_free (data->subject);
1312 g_free (data->plain_body);
1313 g_free (data->html_body);
1314 g_free (data->account_name);
1316 if (data->draft_msg != NULL) {
1317 g_object_unref (data->draft_msg);
1318 data->draft_msg = NULL;
1321 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1322 g_list_free (data->attachments);
1324 g_slice_free (MsgData, data);
1328 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1331 ModestMsgEditWindowPrivate *priv = NULL;
1332 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1334 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1336 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1338 return MODEST_MSG_EDIT_FORMAT_HTML;
1340 return MODEST_MSG_EDIT_FORMAT_TEXT;
1344 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1345 ModestMsgEditFormat format)
1347 ModestMsgEditWindowPrivate *priv;
1349 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1350 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1353 case MODEST_MSG_EDIT_FORMAT_HTML:
1354 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1356 case MODEST_MSG_EDIT_FORMAT_TEXT:
1357 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1360 g_return_if_reached ();
1364 ModestMsgEditFormatState *
1365 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1367 ModestMsgEditFormatState *format_state = NULL;
1368 ModestMsgEditWindowPrivate *priv;
1369 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1371 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1372 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1374 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1376 format_state = g_new0 (ModestMsgEditFormatState, 1);
1377 format_state->bold = buffer_format->bold&0x1;
1378 format_state->italics = buffer_format->italic&0x1;
1379 format_state->bullet = buffer_format->bullet&0x1;
1380 format_state->color = buffer_format->color;
1381 format_state->font_size = buffer_format->font_size;
1382 format_state->font_family = wp_get_font_name (buffer_format->font);
1383 format_state->justification = buffer_format->justification;
1384 g_free (buffer_format);
1386 return format_state;
1391 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1392 const ModestMsgEditFormatState *format_state)
1394 ModestMsgEditWindowPrivate *priv;
1395 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1396 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1397 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1398 g_return_if_fail (format_state != NULL);
1400 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1401 gtk_widget_grab_focus (priv->msg_body);
1402 buffer_format->bold = (format_state->bold != FALSE);
1403 buffer_format->italic = (format_state->italics != FALSE);
1404 buffer_format->color = format_state->color;
1405 buffer_format->font_size = format_state->font_size;
1406 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1407 buffer_format->justification = format_state->justification;
1408 buffer_format->bullet = format_state->bullet;
1410 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1412 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1413 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1414 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1415 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1416 buffer_format->cs.font = (buffer_format->font != current_format->font);
1417 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1418 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1420 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1421 if (buffer_format->cs.bold) {
1422 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1424 if (buffer_format->cs.italic) {
1425 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1427 if (buffer_format->cs.color) {
1428 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1430 if (buffer_format->cs.font_size) {
1431 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1433 if (buffer_format->cs.justification) {
1434 switch (buffer_format->justification) {
1435 case GTK_JUSTIFY_LEFT:
1436 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1438 case GTK_JUSTIFY_CENTER:
1439 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1441 case GTK_JUSTIFY_RIGHT:
1442 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1449 if (buffer_format->cs.font) {
1450 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1452 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1453 if (buffer_format->cs.bullet) {
1454 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((buffer_format->bullet)?1:0));
1456 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1458 g_free (current_format);
1463 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1465 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1467 ModestWindowPrivate *parent_priv;
1468 ModestMsgEditWindowPrivate *priv;
1469 GtkWidget *new_size_menuitem;
1470 GtkWidget *new_font_menuitem;
1472 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1473 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1475 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1476 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1477 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1478 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1480 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1481 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1482 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1485 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1487 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1488 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1490 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1491 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1493 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1494 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1496 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1497 G_CALLBACK (modest_msg_edit_window_color_button_change),
1499 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1500 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1501 G_CALLBACK (modest_msg_edit_window_color_button_change),
1504 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1505 buffer_format->font_size))->data);
1506 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1510 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1511 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1512 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1514 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1515 G_CALLBACK (modest_msg_edit_window_size_change),
1517 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1518 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1519 G_CALLBACK (modest_msg_edit_window_size_change),
1523 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1524 buffer_format->font))->data);
1525 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1529 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1530 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1531 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1533 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1534 G_CALLBACK (modest_msg_edit_window_font_change),
1536 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1537 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1538 G_CALLBACK (modest_msg_edit_window_font_change),
1542 g_free (buffer_format);
1548 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1551 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1552 ModestMsgEditWindowPrivate *priv;
1553 GtkWidget *dialog = NULL;
1555 const GdkColor *new_color = NULL;
1557 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1558 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1560 #ifdef MODEST_HILDON_VERSION_0
1561 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1562 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1564 dialog = hildon_color_chooser_new ();
1565 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1566 #endif /*MODEST_HILDON_VERSION_0*/
1567 g_free (buffer_format);
1569 response = gtk_dialog_run (GTK_DIALOG (dialog));
1571 case GTK_RESPONSE_OK: {
1572 #ifdef MODEST_HILDON_VERSION_0
1573 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1576 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1578 #endif /*MODEST_HILDON_VERSION_0*/
1585 gtk_widget_destroy (dialog);
1587 if (new_color != NULL)
1588 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1593 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1596 ModestMsgEditWindowPrivate *priv;
1597 GtkWidget *dialog = NULL;
1599 GdkColor *old_color = NULL;
1600 const GdkColor *new_color = NULL;
1602 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1603 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1605 #ifdef MODEST_HILDON_VERSION_0
1606 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1607 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1609 dialog = hildon_color_chooser_new ();
1610 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1611 #endif /*MODEST_HILDON_VERSION_9*/
1613 response = gtk_dialog_run (GTK_DIALOG (dialog));
1615 case GTK_RESPONSE_OK: {
1616 #ifdef MODEST_HILDON_VERSION_0
1617 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1620 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1622 #endif /*MODEST_HILDON_VERSION_0*/
1628 gtk_widget_destroy (dialog);
1630 if (new_color != NULL)
1631 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1635 static TnyStream* create_stream_for_uri (const gchar* uri)
1640 TnyStream *result = NULL;
1642 GnomeVFSHandle *handle = NULL;
1643 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1644 if (test == GNOME_VFS_OK) {
1645 /* Create the tinymail stream: */
1646 /* Presumably tinymai will call gnome_vfs_close (handle) later. */
1647 result = TNY_STREAM (tny_vfs_stream_new (handle));
1654 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1657 ModestMsgEditWindowPrivate *priv;
1658 GtkWidget *dialog = NULL;
1660 GSList *uris = NULL;
1661 GSList *uri_node = NULL;
1663 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1665 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1666 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1667 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1669 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1671 response = gtk_dialog_run (GTK_DIALOG (dialog));
1673 case GTK_RESPONSE_OK:
1674 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1679 gtk_widget_destroy (dialog);
1681 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1683 GnomeVFSHandle *handle = NULL;
1684 GnomeVFSResult result;
1685 GtkTextIter position;
1686 GtkTextMark *insert_mark;
1688 uri = (const gchar *) uri_node->data;
1689 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1690 if (result == GNOME_VFS_OK) {
1692 GnomeVFSFileInfo info;
1693 gchar *filename, *basename, *escaped_filename;
1694 TnyMimePart *mime_part;
1696 const gchar *mime_type = NULL;
1697 GnomeVFSURI *vfs_uri;
1699 vfs_uri = gnome_vfs_uri_new (uri);
1701 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1702 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1703 g_free (escaped_filename);
1704 gnome_vfs_uri_unref (vfs_uri);
1706 if (gnome_vfs_get_file_info (uri, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
1707 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1709 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1711 mime_part = tny_platform_factory_new_mime_part
1712 (modest_runtime_get_platform_factory ());
1714 TnyStream *stream = create_stream_for_uri (uri);
1715 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1717 content_id = g_strdup_printf ("%d", priv->last_cid);
1718 tny_mime_part_set_content_id (mime_part, content_id);
1719 g_free (content_id);
1722 basename = g_path_get_basename (filename);
1723 tny_mime_part_set_filename (mime_part, basename);
1726 pixbuf = pixbuf_from_stream (stream, mime_type);
1728 if (pixbuf != NULL) {
1729 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1730 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1731 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1734 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1735 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1737 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1738 gtk_widget_show_all (priv->attachments_caption);
1739 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1749 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
1752 ModestMsgEditWindowPrivate *priv;
1753 GtkWidget *dialog = NULL;
1755 GSList *uris = NULL;
1758 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1760 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1761 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
1762 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1764 response = gtk_dialog_run (GTK_DIALOG (dialog));
1766 case GTK_RESPONSE_OK:
1767 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1772 gtk_widget_destroy (dialog);
1774 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1775 const gchar *uri = (const gchar *) uri_node->data;
1776 modest_msg_edit_window_attach_file_one (window, uri);
1778 g_slist_foreach (uris, (GFunc) g_free, NULL);
1779 g_slist_free (uris);
1783 modest_msg_edit_window_attach_file_one (
1784 ModestMsgEditWindow *window,
1787 g_return_if_fail (window);
1788 g_return_if_fail (uri);
1790 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1793 GnomeVFSHandle *handle = NULL;
1794 GnomeVFSResult result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1795 if (result == GNOME_VFS_OK) {
1796 TnyMimePart *mime_part;
1798 const gchar *mime_type = NULL;
1800 gchar *escaped_filename;
1803 GnomeVFSFileInfo info;
1804 GnomeVFSURI *vfs_uri;
1806 vfs_uri = gnome_vfs_uri_new (uri);
1809 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1810 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1811 g_free (escaped_filename);
1812 gnome_vfs_uri_unref (vfs_uri);
1814 if (gnome_vfs_get_file_info (uri,
1816 GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
1817 GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1819 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1820 mime_part = tny_platform_factory_new_mime_part
1821 (modest_runtime_get_platform_factory ());
1822 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1824 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1826 content_id = g_strdup_printf ("%d", priv->last_cid);
1827 tny_mime_part_set_content_id (mime_part, content_id);
1828 g_free (content_id);
1831 basename = g_path_get_basename (filename);
1832 tny_mime_part_set_filename (mime_part, basename);
1835 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1836 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1838 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1839 gtk_widget_show_all (priv->attachments_caption);
1840 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1846 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1849 ModestMsgEditWindowPrivate *priv;
1850 gboolean clean_list = FALSE;
1852 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1853 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1855 if (att_list == NULL) {
1856 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1860 if (att_list == NULL) {
1861 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1863 GtkWidget *confirmation_dialog = NULL;
1864 gboolean dialog_response;
1866 gchar *message = NULL;
1867 const gchar *filename = NULL;
1869 if (att_list->next == NULL) {
1870 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1874 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1875 att_list->next == NULL), filename);
1876 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1878 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1879 gtk_widget_destroy (confirmation_dialog);
1880 if (!dialog_response) {
1882 g_list_free (att_list);
1885 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1887 for (node = att_list; node != NULL; node = g_list_next (node)) {
1888 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1889 const gchar *att_id;
1890 priv->attachments = g_list_remove (priv->attachments, mime_part);
1892 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1894 if (priv->attachments == NULL)
1895 gtk_widget_hide (priv->attachments_caption);
1896 att_id = tny_mime_part_get_content_id (mime_part);
1898 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1900 g_object_unref (mime_part);
1901 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1906 g_list_free (att_list);
1910 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1913 ModestMsgEditWindowPrivate *priv;
1914 GdkColor *new_color;
1915 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1917 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1918 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1921 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1923 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1925 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1927 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1932 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1935 ModestMsgEditWindowPrivate *priv;
1936 gint new_size_index;
1937 ModestMsgEditWindow *window;
1940 window = MODEST_MSG_EDIT_WINDOW (userdata);
1941 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1942 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1944 if (gtk_check_menu_item_get_active (menu_item)) {
1946 WPTextBufferFormat format;
1948 memset (&format, 0, sizeof (format));
1949 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1951 label = gtk_bin_get_child (GTK_BIN (menu_item));
1953 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1954 format.cs.font_size = TRUE;
1955 format.cs.text_position = TRUE;
1956 format.cs.font = TRUE;
1957 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1958 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1960 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1961 (gpointer) wp_get_font_size_index (new_size_index, 12)))
1962 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1964 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1965 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1966 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1972 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1975 ModestMsgEditWindowPrivate *priv;
1976 gint new_font_index;
1977 ModestMsgEditWindow *window;
1980 window = MODEST_MSG_EDIT_WINDOW (userdata);
1981 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1982 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1984 if (gtk_check_menu_item_get_active (menu_item)) {
1987 label = gtk_bin_get_child (GTK_BIN (menu_item));
1989 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1991 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1992 (gpointer) new_font_index))
1993 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1995 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1996 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1997 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2003 modest_msg_edit_window_set_zoom (ModestWindow *window,
2006 ModestMsgEditWindowPrivate *priv;
2007 ModestWindowPrivate *parent_priv;
2008 GtkRadioAction *zoom_radio_action;
2010 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2012 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2013 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2014 priv->zoom_level = zoom;
2015 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom*DEFAULT_FONT_SCALE);
2017 /* Zoom level menu options should be updated with the current zoom level */
2018 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2019 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2020 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2021 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2022 /* FIXME: Not availible before Gtk 2.10 */
2024 gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
2029 modest_msg_edit_window_get_zoom (ModestWindow *window)
2031 ModestMsgEditWindowPrivate *priv;
2033 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
2035 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2036 return priv->zoom_level;
2040 zoom_allowed (ModestMsgEditWindow *window)
2044 focus = gtk_window_get_focus (GTK_WINDOW (window));
2045 return (focus != NULL && WP_IS_TEXT_VIEW (focus));
2049 modest_msg_edit_window_zoom_plus (ModestWindow *window)
2051 ModestWindowPrivate *parent_priv;
2052 GtkRadioAction *zoom_radio_action;
2053 GSList *group, *node;
2055 /* First we check if the text view is focused. If not, zooming is not allowed */
2056 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2057 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2061 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2062 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2063 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2065 group = gtk_radio_action_get_group (zoom_radio_action);
2067 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
2068 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
2072 for (node = group; node != NULL; node = g_slist_next (node)) {
2073 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
2074 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
2082 modest_msg_edit_window_zoom_minus (ModestWindow *window)
2084 ModestWindowPrivate *parent_priv;
2085 GtkRadioAction *zoom_radio_action;
2086 GSList *group, *node;
2088 /* First we check if the text view is focused. If not, zooming is not allowed */
2089 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2090 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2094 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2095 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2096 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2098 group = gtk_radio_action_get_group (zoom_radio_action);
2100 for (node = group; node != NULL; node = g_slist_next (node)) {
2101 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
2102 if (node->next != NULL) {
2103 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
2106 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
2114 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2116 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2117 ModestWindowPrivate *parent_priv;
2118 ModestWindowMgr *mgr;
2119 gboolean is_fullscreen;
2120 GtkAction *fs_toggle_action;
2123 mgr = modest_runtime_get_window_mgr ();
2124 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2126 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2128 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2129 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2130 if (is_fullscreen != active)
2131 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2139 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
2141 ModestWindowPrivate *parent_priv;
2142 GtkAction *fs_toggle_action;
2145 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2147 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2148 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
2149 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
2153 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2156 ModestMsgEditWindowPrivate *priv = NULL;
2157 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2159 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2160 if (!priv->update_caption_visibility)
2163 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2165 gtk_widget_show (priv->cc_caption);
2167 gtk_widget_hide (priv->cc_caption);
2169 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2173 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2176 ModestMsgEditWindowPrivate *priv = NULL;
2177 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2179 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2180 if (!priv->update_caption_visibility)
2183 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2185 gtk_widget_show (priv->bcc_caption);
2187 gtk_widget_hide (priv->bcc_caption);
2189 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2193 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2194 ModestRecptEditor *editor)
2196 ModestMsgEditWindowPrivate *priv;
2198 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2199 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2200 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2202 if (editor == NULL) {
2203 GtkWidget *view_focus;
2204 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2206 /* This code should be kept in sync with ModestRecptEditor. The
2207 textview inside the recpt editor is the one that really gets the
2208 focus. As it's inside a scrolled window, and this one inside the
2209 hbox recpt editor inherits from, we'll need to go up in the
2210 hierarchy to know if the text view is part of the recpt editor
2211 or if it's a different text entry */
2213 if (gtk_widget_get_parent (view_focus)) {
2214 GtkWidget *first_parent;
2216 first_parent = gtk_widget_get_parent (view_focus);
2217 if (gtk_widget_get_parent (first_parent) &&
2218 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2219 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2224 editor = MODEST_RECPT_EDITOR (priv->to_field);
2228 modest_address_book_select_addresses (editor);
2233 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2235 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2237 modest_msg_edit_window_open_addressbook (window, NULL);
2241 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2242 gboolean show_toolbar)
2244 ModestWindowPrivate *parent_priv;
2246 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2247 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2249 /* FIXME: we can not just use the code of
2250 modest_msg_edit_window_setup_toolbar because it has a
2251 mixture of both initialization and creation code. */
2254 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2256 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2260 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2261 TnyHeaderFlags priority_flags)
2263 ModestMsgEditWindowPrivate *priv;
2264 ModestWindowPrivate *parent_priv;
2266 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2268 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2269 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2270 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2272 if (priv->priority_flags != priority_flags) {
2273 GtkAction *priority_action = NULL;
2275 priv->priority_flags = priority_flags;
2277 switch (priority_flags) {
2278 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2279 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2280 gtk_widget_show (priv->priority_icon);
2281 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2282 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2284 case TNY_HEADER_FLAG_LOW_PRIORITY:
2285 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2286 gtk_widget_show (priv->priority_icon);
2287 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2288 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2291 gtk_widget_hide (priv->priority_icon);
2292 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2293 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2296 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2297 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2302 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2305 ModestMsgEditWindowPrivate *priv;
2306 ModestWindowPrivate *parent_priv;
2307 gint current_format;
2309 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2311 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2312 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2314 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2315 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2317 if (current_format != file_format) {
2318 switch (file_format) {
2319 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2320 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2322 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2326 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2327 response = gtk_dialog_run (GTK_DIALOG (dialog));
2328 gtk_widget_destroy (dialog);
2329 if (response == GTK_RESPONSE_OK) {
2330 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2332 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2333 modest_maemo_toggle_action_set_active_block_notify (action, TRUE);
2338 update_dimmed (window);
2343 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2346 ModestMsgEditWindowPrivate *priv;
2347 WPTextBufferFormat oldfmt, fmt;
2348 gint old_position = 0;
2352 GdkColor *color = NULL;
2353 gboolean bold, bold_set, italic, italic_set;
2354 gboolean underline, underline_set;
2355 gboolean strikethrough, strikethrough_set;
2356 gboolean position_set;
2357 gboolean font_size_set, font_set, color_set;
2360 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2361 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2363 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2365 /* First we get the currently selected font information */
2366 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2367 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2369 switch (oldfmt.text_position) {
2370 case TEXT_POSITION_NORMAL:
2373 case TEXT_POSITION_SUPERSCRIPT:
2381 g_object_set (G_OBJECT (dialog),
2382 "bold", oldfmt.bold != FALSE,
2383 "bold-set", !oldfmt.cs.bold,
2384 "underline", oldfmt.underline != FALSE,
2385 "underline-set", !oldfmt.cs.underline,
2386 "italic", oldfmt.italic != FALSE,
2387 "italic-set", !oldfmt.cs.italic,
2388 "strikethrough", oldfmt.strikethrough != FALSE,
2389 "strikethrough-set", !oldfmt.cs.strikethrough,
2390 "color", &oldfmt.color,
2391 "color-set", !oldfmt.cs.color,
2392 "size", wp_font_size[oldfmt.font_size],
2393 "size-set", !oldfmt.cs.font_size,
2394 "position", old_position,
2395 "position-set", !oldfmt.cs.text_position,
2396 "family", wp_get_font_name (oldfmt.font),
2397 "family-set", !oldfmt.cs.font,
2400 gtk_widget_show_all (dialog);
2401 response = gtk_dialog_run (GTK_DIALOG (dialog));
2402 if (response == GTK_RESPONSE_OK) {
2404 g_object_get( dialog,
2406 "bold-set", &bold_set,
2407 "underline", &underline,
2408 "underline-set", &underline_set,
2410 "italic-set", &italic_set,
2411 "strikethrough", &strikethrough,
2412 "strikethrough-set", &strikethrough_set,
2414 "color-set", &color_set,
2416 "size-set", &font_size_set,
2417 "family", &font_name,
2418 "family-set", &font_set,
2419 "position", &position,
2420 "position-set", &position_set,
2425 if (response == GTK_RESPONSE_OK) {
2426 memset(&fmt, 0, sizeof(fmt));
2432 fmt.italic = italic;
2433 fmt.cs.italic = TRUE;
2435 if (underline_set) {
2436 fmt.underline = underline;
2437 fmt.cs.underline = TRUE;
2439 if (strikethrough_set) {
2440 fmt.strikethrough = strikethrough;
2441 fmt.cs.strikethrough = TRUE;
2446 ? TEXT_POSITION_NORMAL
2447 : ( ( position == 1 )
2448 ? TEXT_POSITION_SUPERSCRIPT
2449 : TEXT_POSITION_SUBSCRIPT );
2450 fmt.cs.text_position = TRUE;
2454 fmt.cs.color = TRUE;
2457 fmt.font = wp_get_font_index(font_name,
2462 if (font_size_set) {
2463 fmt.font_size = wp_get_font_size_index(
2464 font_size, DEFAULT_FONT_SIZE);
2465 fmt.cs.font_size = TRUE;
2467 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2469 gtk_widget_destroy (dialog);
2471 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2475 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2477 ModestMsgEditWindowPrivate *priv;
2479 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2480 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2482 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2484 update_dimmed (window);
2489 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2491 ModestMsgEditWindowPrivate *priv;
2493 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2494 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2496 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2498 update_dimmed (window);
2503 update_dimmed (ModestMsgEditWindow *window)
2505 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2506 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2510 gboolean editor_focused;
2512 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2513 editor_focused = gtk_widget_is_focus (priv->msg_body);
2515 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2516 gtk_action_set_sensitive (action, rich_text && editor_focused);
2517 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2518 gtk_action_set_sensitive (action, rich_text && editor_focused);
2519 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2520 gtk_action_set_sensitive (action, rich_text && editor_focused);
2521 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2522 gtk_action_set_sensitive (action, rich_text && editor_focused);
2523 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2524 gtk_action_set_sensitive (action, rich_text && editor_focused);
2525 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2526 gtk_action_set_sensitive (action, rich_text && editor_focused);
2527 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2528 gtk_action_set_sensitive (action, rich_text && editor_focused);
2529 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2530 gtk_action_set_sensitive (action, rich_text && editor_focused);
2531 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2532 gtk_action_set_sensitive (action, rich_text && editor_focused);
2533 widget = priv->font_color_button;
2534 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2535 widget = priv->font_size_toolitem;
2536 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2537 widget = priv->font_face_toolitem;
2538 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2542 setup_insensitive_handlers (ModestMsgEditWindow *window)
2544 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2545 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2548 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2549 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2550 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2551 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2552 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2553 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2554 widget = priv->font_color_button;
2555 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2556 widget = priv->font_size_toolitem;
2557 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2558 widget = priv->font_face_toolitem;
2559 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2564 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2566 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2569 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2570 gtk_action_set_sensitive (action, can_undo);
2574 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2576 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2579 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/RedoMenu");
2580 gtk_action_set_sensitive (action, can_redo);
2584 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2587 GtkTextIter match_start, match_end;
2589 if (image_id == NULL)
2592 gtk_text_buffer_get_start_iter (buffer, &iter);
2594 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2595 GSList *tags = gtk_text_iter_get_tags (&match_start);
2597 for (node = tags; node != NULL; node = g_slist_next (node)) {
2598 GtkTextTag *tag = (GtkTextTag *) node->data;
2599 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2600 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2601 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2603 offset = gtk_text_iter_get_offset (&match_start);
2604 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2605 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2609 gtk_text_iter_forward_char (&iter);
2614 msg_body_focus (GtkWidget *focus,
2615 GdkEventFocus *event,
2619 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2624 recpt_field_changed (GtkTextBuffer *buffer,
2625 ModestMsgEditWindow *editor)
2627 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2628 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2629 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2630 gboolean dim = FALSE;
2633 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2634 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2635 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2637 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2638 gtk_text_buffer_get_char_count (cc_buffer) +
2639 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2641 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2642 gtk_action_set_sensitive (action, !dim);
2643 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2644 gtk_action_set_sensitive (action, !dim);
2648 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2650 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2654 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2656 gboolean rich_text, editor_focused;
2658 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2659 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2660 editor_focused = gtk_widget_is_focus (priv->msg_body);
2663 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2664 else if (!editor_focused)
2665 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2669 reset_modified (ModestMsgEditWindow *editor)
2671 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2672 GtkTextBuffer *buffer;
2674 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2675 gtk_text_buffer_set_modified (buffer, FALSE);
2676 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2677 gtk_text_buffer_set_modified (buffer, FALSE);
2678 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2679 gtk_text_buffer_set_modified (buffer, FALSE);
2680 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2684 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2686 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2687 GtkTextBuffer *buffer;
2689 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2690 if (gtk_text_buffer_get_modified (buffer))
2692 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2693 if (gtk_text_buffer_get_modified (buffer))
2695 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2696 if (gtk_text_buffer_get_modified (buffer))
2698 if (gtk_text_buffer_get_modified (priv->text_buffer))
2705 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
2707 ModestMsgEditWindowPrivate *priv = NULL;
2709 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2710 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2712 /* check if there's no recipient added */
2713 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2714 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2715 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2716 /* no recipient contents, then select contacts */
2717 modest_msg_edit_window_open_addressbook (window, NULL);
2721 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook))
2723 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook))
2725 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook))
2728 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2735 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2736 ModestMsgEditWindow *window)
2738 modest_msg_edit_window_offer_attach_file (window);
2742 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2744 ModestMsgEditWindow *window)
2746 ModestWindowPrivate *parent_priv;
2747 ModestMsgEditWindowPrivate *priv;
2749 gboolean has_selection;
2751 GList *selected_attachments = NULL;
2752 gint n_att_selected = 0;
2754 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2755 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2757 if (!GTK_WIDGET_VISIBLE (window))
2759 has_selection = gtk_clipboard_wait_for_targets (clipboard, NULL, NULL);
2760 focused = gtk_window_get_focus (GTK_WINDOW (window));
2762 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2763 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2764 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2765 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2767 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2768 n_att_selected = g_list_length (selected_attachments);
2769 g_list_free (selected_attachments);
2771 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2772 gtk_action_set_sensitive (action, n_att_selected == 1);
2774 update_paste_dimming (window);
2778 update_window_title (ModestMsgEditWindow *window)
2780 ModestMsgEditWindowPrivate *priv = NULL;
2781 const gchar *subject;
2783 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2784 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2785 if (subject == NULL || subject[0] == '\0')
2786 subject = _("mail_va_new_email");
2788 gtk_window_set_title (GTK_WINDOW (window), subject);
2793 subject_field_changed (GtkEditable *editable,
2794 ModestMsgEditWindow *window)
2796 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2797 update_window_title (window);
2798 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2802 message_is_empty (ModestMsgEditWindow *window)
2804 ModestMsgEditWindowPrivate *priv = NULL;
2806 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2807 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2809 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
2810 * so we can ignore markup.
2812 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
2815 count = gtk_text_buffer_get_char_count (buf);
2821 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2824 ModestMsgEditWindowPrivate *priv = NULL;
2826 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2827 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2829 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2832 gtk_widget_show_all (priv->find_toolbar);
2833 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2835 gtk_widget_hide_all (priv->find_toolbar);
2836 gtk_widget_grab_focus (priv->msg_body);
2842 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2844 GtkTextIter *match_start,
2845 GtkTextIter *match_end)
2847 GtkTextIter end_iter;
2848 gchar *str_casefold;
2851 gchar *range_casefold;
2854 gboolean result = FALSE;
2861 gtk_text_iter_forward_to_end (&end_iter);
2863 str_casefold = g_utf8_casefold (str, -1);
2864 str_chars_n = strlen (str);
2866 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2867 range_casefold = g_utf8_casefold (range_text, -1);
2868 range_chars_n = strlen (range_casefold);
2870 if (range_chars_n < str_chars_n) {
2871 g_free (str_casefold);
2872 g_free (range_text);
2873 g_free (range_casefold);
2877 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2878 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2879 if (!g_utf8_collate (range_subtext, str_casefold)) {
2880 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2882 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2883 match_start, match_end, NULL);
2884 g_free (found_text);
2886 g_free (range_subtext);
2890 g_free (str_casefold);
2891 g_free (range_text);
2892 g_free (range_casefold);
2899 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2900 ModestMsgEditWindow *window)
2902 gchar *current_search = NULL;
2903 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2905 GtkTextIter selection_start, selection_end;
2906 GtkTextIter match_start, match_end;
2907 gboolean continue_search = FALSE;
2909 if (message_is_empty (window)) {
2910 g_free (priv->last_search);
2911 priv->last_search = NULL;
2912 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
2916 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2917 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2918 g_free (current_search);
2919 g_free (priv->last_search);
2920 priv->last_search = NULL;
2921 /* Information banner about empty search */
2922 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2926 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2927 continue_search = TRUE;
2929 g_free (priv->last_search);
2930 priv->last_search = g_strdup (current_search);
2933 if (continue_search) {
2934 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2935 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2936 &match_start, &match_end);
2938 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2940 GtkTextIter buffer_start;
2941 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2942 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2943 &match_start, &match_end);
2945 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2948 /* Mark as selected the string found in search */
2950 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2951 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2953 g_free (priv->last_search);
2954 priv->last_search = NULL;
2956 g_free (current_search);
2960 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2961 ModestMsgEditWindow *window)
2963 GtkToggleAction *toggle;
2964 ModestWindowPrivate *parent_priv;
2965 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2967 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2968 gtk_toggle_action_set_active (toggle, FALSE);
2973 update_paste_dimming (ModestMsgEditWindow *window)
2975 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2976 GtkAction *action = NULL;
2977 GtkClipboard *clipboard = NULL;
2978 ModestEmailClipboard *e_clipboard;
2982 focused = gtk_window_get_focus (GTK_WINDOW (window));
2984 e_clipboard = modest_runtime_get_email_clipboard ();
2985 if (!modest_email_clipboard_cleared (e_clipboard)) {
2988 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2989 active = gtk_clipboard_wait_is_text_available (clipboard);
2993 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2997 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2998 gtk_action_set_sensitive (action, active);
3003 update_select_all_dimming (ModestMsgEditWindow *window)
3006 gboolean dimmed = FALSE;
3008 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3010 focused = gtk_window_get_focus (GTK_WINDOW (window));
3011 if (GTK_IS_ENTRY (focused)) {
3012 const gchar *current_text;
3013 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
3014 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
3015 } else if (GTK_IS_TEXT_VIEW (focused)) {
3016 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
3017 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
3018 } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
3021 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
3022 gtk_action_set_sensitive (action, !dimmed);
3026 update_zoom_dimming (ModestMsgEditWindow *window)
3029 gboolean dimmed = FALSE;
3031 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3033 focused = gtk_window_get_focus (GTK_WINDOW (window));
3034 dimmed = ! WP_IS_TEXT_VIEW (focused);
3035 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
3036 gtk_action_set_sensitive (action, !dimmed);
3040 edit_menu_activated (GtkAction *action,
3043 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3045 update_select_all_dimming (window);
3046 update_paste_dimming (window);
3049 view_menu_activated (GtkAction *action,
3052 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3054 update_zoom_dimming (window);
3058 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3060 ModestMsgEditWindowPrivate *priv;
3062 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3067 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3070 ModestMsgEditWindowPrivate *priv;
3072 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3078 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3081 ModestMsgEditWindowPrivate *priv;
3082 TnyHeader *header = NULL;
3084 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3085 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3087 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3088 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3090 if (priv->draft_msg != NULL) {
3091 header = tny_msg_get_header (priv->draft_msg);
3092 if (TNY_IS_HEADER (header)) {
3093 modest_window_mgr_unregister_header (mgr, header);
3095 g_object_unref (priv->draft_msg);
3098 if (draft != NULL) {
3099 g_object_ref (draft);
3100 header = tny_msg_get_header (draft);
3101 if (TNY_IS_HEADER (header))
3102 modest_window_mgr_register_header (mgr, header);
3105 priv->draft_msg = draft;
3109 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3110 GtkTextIter *start, GtkTextIter *end,
3113 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3114 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3117 if (tag == NULL+13) return;
3118 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3119 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3120 replace_with_attachments (window, priv->attachments);
3125 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3128 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3130 g_return_if_fail (TNY_IS_MIME_PART (part));
3131 priv->attachments = g_list_prepend (priv->attachments, part);
3132 g_object_ref (part);
3133 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part);
3134 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3135 gtk_widget_show_all (priv->attachments_caption);
3136 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);