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;
260 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
261 MODEST_TYPE_MSG_EDIT_WINDOW, \
262 ModestMsgEditWindowPrivate))
264 static GtkWindowClass *parent_class = NULL;
266 /* uncomment the following if you have defined any signals */
267 /* static guint signals[LAST_SIGNAL] = {0}; */
270 modest_msg_edit_window_get_type (void)
272 static GType my_type = 0;
274 static const GTypeInfo my_info = {
275 sizeof(ModestMsgEditWindowClass),
276 NULL, /* base init */
277 NULL, /* base finalize */
278 (GClassInitFunc) modest_msg_edit_window_class_init,
279 NULL, /* class finalize */
280 NULL, /* class data */
281 sizeof(ModestMsgEditWindow),
283 (GInstanceInitFunc) modest_msg_edit_window_init,
286 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
287 "ModestMsgEditWindow",
290 wp_text_buffer_library_init ();
296 save_state (ModestWindow *self)
298 modest_widget_memory_save (modest_runtime_get_conf(),
299 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
304 restore_settings (ModestMsgEditWindow *self)
306 modest_widget_memory_restore (modest_runtime_get_conf(),
307 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
312 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
314 GObjectClass *gobject_class;
315 ModestWindowClass *modest_window_class;
316 gobject_class = (GObjectClass*) klass;
317 modest_window_class = (ModestWindowClass*) klass;
319 parent_class = g_type_class_peek_parent (klass);
320 gobject_class->finalize = modest_msg_edit_window_finalize;
322 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
323 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
324 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
325 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
326 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
327 modest_window_class->save_state_func = save_state;
328 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
330 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
334 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
336 ModestMsgEditWindowPrivate *priv;
337 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
339 priv->msg_body = NULL;
340 priv->from_field = NULL;
341 priv->to_field = NULL;
342 priv->cc_field = NULL;
343 priv->bcc_field = NULL;
344 priv->subject_field = NULL;
345 priv->attachments = NULL;
347 priv->zoom_level = 1.0;
349 priv->cc_caption = NULL;
350 priv->bcc_caption = NULL;
351 priv->update_caption_visibility = FALSE;
353 priv->priority_flags = 0;
355 priv->find_toolbar = NULL;
356 priv->last_search = NULL;
358 priv->draft_msg = NULL;
359 priv->outbox_msg = NULL;
360 priv->msg_uid = NULL;
361 priv->clipboard_change_handler_id = 0;
364 priv->last_vadj_upper = 0;
368 /* FIXME: this is a dup from the one in gtk/ */
371 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
373 static ModestPairList*
374 get_transports (void)
376 GSList *transports = NULL;
378 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
379 GSList *accounts = modest_account_mgr_account_names (account_mgr,
380 TRUE /* only enabled accounts. */);
382 GSList *cursor = accounts;
384 gchar *account_name = cursor->data;
385 gchar *from_string = NULL;
387 from_string = modest_account_mgr_get_from_string (account_mgr,
391 if (from_string && account_name) {
392 gchar *name = account_name;
393 ModestPair *pair = modest_pair_new ((gpointer) name,
394 (gpointer) from_string , TRUE);
395 transports = g_slist_prepend (transports, pair);
398 cursor = cursor->next;
400 g_slist_free (accounts); /* only free the accounts, not the elements,
401 * because they are used in the pairlist */
405 void vadj_changed (GtkAdjustment *adj,
406 ModestMsgEditWindow *window)
408 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
410 GdkRectangle rectangle, cursor_rectangle;
411 GtkTextIter position;
415 /* We detect if cursor is visible using the full height, not only the center. This
417 gtk_text_view_get_visible_rect (GTK_TEXT_VIEW (priv->msg_body), &rectangle);
418 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer),
420 gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer)));
421 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &position, &cursor_rectangle);
423 cursor_bottom = (cursor_rectangle.y + cursor_rectangle.height);
424 visible = (cursor_rectangle.y >= rectangle.y) && (cursor_bottom < (rectangle.y + rectangle.height));
426 if (gtk_widget_is_focus (priv->msg_body) &&
428 if (priv->last_vadj_upper != adj->upper) {
431 insert = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
432 gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (priv->msg_body),
433 insert, 0.1, FALSE, 0.0, 0.0);
436 priv->last_vadj_upper = adj->upper;
441 init_window (ModestMsgEditWindow *obj)
443 GtkWidget *from_caption, *to_caption, *subject_caption;
444 GtkWidget *main_vbox;
445 ModestMsgEditWindowPrivate *priv;
447 GtkSizeGroup *size_group;
449 GtkWidget *subject_box;
450 GtkWidget *attachment_icon;
451 GtkWidget *window_box;
452 #if (GTK_MINOR_VERSION >= 10)
453 GdkAtom deserialize_type;
455 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
457 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
459 /* Note: This ModestPairList* must exist for as long as the combo
460 * that uses it, because the ModestComboBox uses the ID opaquely,
461 * so it can't know how to manage its memory. */
462 priv->from_field_protos = get_transports ();
464 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
466 priv->to_field = modest_recpt_editor_new ();
467 priv->cc_field = modest_recpt_editor_new ();
468 priv->bcc_field = modest_recpt_editor_new ();
469 subject_box = gtk_hbox_new (FALSE, 0);
470 priv->priority_icon = gtk_image_new ();
471 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
472 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
473 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
474 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
475 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
476 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
477 priv->add_attachment_button = gtk_button_new ();
478 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
479 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
480 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
481 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
482 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
483 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
484 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
485 priv->attachments_view = modest_attachments_view_new (NULL);
487 priv->header_box = gtk_vbox_new (FALSE, 0);
489 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
490 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
491 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
492 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
493 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
494 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
495 g_object_unref (size_group);
497 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
498 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
499 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
500 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
501 gtk_size_group_add_widget (size_group, priv->subject_field);
502 gtk_size_group_add_widget (size_group, priv->attachments_view);
503 g_object_unref (size_group);
505 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
506 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
507 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
508 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
509 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
510 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
511 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
514 priv->msg_body = wp_text_view_new ();
515 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
516 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
517 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
518 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
519 #if (GTK_MINOR_VERSION >= 10)
520 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
521 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
523 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
524 deserialize_type, TRUE);
526 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
528 priv->find_toolbar = hildon_find_toolbar_new (NULL);
529 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
531 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
533 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
534 G_CALLBACK (text_buffer_refresh_attributes), obj);
535 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
536 G_CALLBACK (text_buffer_can_undo), obj);
537 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
538 G_CALLBACK (text_buffer_can_redo), obj);
539 g_signal_connect (G_OBJECT (obj), "window-state-event",
540 G_CALLBACK (modest_msg_edit_window_window_state_event),
542 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
543 G_CALLBACK (text_buffer_apply_tag), obj);
544 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
545 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
546 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
547 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
548 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
549 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
551 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
552 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
554 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
555 G_CALLBACK (msg_body_focus), obj);
556 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
557 G_CALLBACK (msg_body_focus), obj);
558 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
559 "changed", G_CALLBACK (recpt_field_changed), obj);
560 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
561 "changed", G_CALLBACK (recpt_field_changed), obj);
562 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
563 "changed", G_CALLBACK (recpt_field_changed), obj);
564 recpt_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
565 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
567 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
568 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
570 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
571 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
572 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
573 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
575 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
577 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
578 frame = gtk_frame_new (NULL);
579 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
581 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
582 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
583 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
585 G_CALLBACK (vadj_changed),
587 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
589 window_box = gtk_vbox_new (FALSE, 0);
590 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
591 gtk_container_add (GTK_CONTAINER(obj), window_box);
592 priv->scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
593 gtk_container_add (GTK_CONTAINER (frame), priv->scroll_area);
595 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
596 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
601 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
603 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
605 if (g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
606 priv->clipboard_change_handler_id))
607 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
608 priv->clipboard_change_handler_id);
612 modest_msg_edit_window_finalize (GObject *obj)
614 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
616 /* Sanity check: shouldn't be needed, the window mgr should
617 call this function before */
618 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
620 if (priv->draft_msg != NULL) {
621 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
622 if (TNY_IS_HEADER (header)) {
623 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
624 modest_window_mgr_unregister_header (mgr, header);
626 g_object_unref (priv->draft_msg);
627 priv->draft_msg = NULL;
629 if (priv->outbox_msg != NULL) {
630 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
631 if (TNY_IS_HEADER (header)) {
632 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
633 modest_window_mgr_unregister_header (mgr, header);
635 g_object_unref (priv->outbox_msg);
636 priv->outbox_msg = NULL;
638 if (priv->msg_uid != NULL) {
639 g_free (priv->msg_uid);
640 priv->msg_uid = NULL;
643 /* This had to stay alive for as long as the combobox that used it: */
644 modest_pair_list_free (priv->from_field_protos);
646 G_OBJECT_CLASS(parent_class)->finalize (obj);
650 menubar_to_menu (GtkUIManager *ui_manager)
652 GtkWidget *main_menu;
656 /* Create new main menu */
657 main_menu = gtk_menu_new();
659 /* Get the menubar from the UI manager */
660 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
662 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
666 menu = GTK_WIDGET (iter->data);
667 gtk_widget_reparent(menu, main_menu);
669 iter = g_list_next (iter);
675 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type)
677 GdkPixbufLoader *loader;
680 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
685 tny_stream_reset (TNY_STREAM (stream));
686 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
687 unsigned char read_buffer[128];
689 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
690 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
694 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
695 g_object_ref (pixbuf);
696 gdk_pixbuf_loader_close (loader, NULL);
697 g_object_unref (loader);
699 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
700 GdkPixbuf *new_pixbuf;
702 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
703 gdk_pixbuf_get_width (pixbuf);
704 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
705 g_object_unref (pixbuf);
713 replace_with_attachments (ModestMsgEditWindow *self, GList *attachments)
715 ModestMsgEditWindowPrivate *priv;
718 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
720 for (node = attachments; node != NULL; node = g_list_next (node)) {
721 TnyMimePart *part = (TnyMimePart *) node->data;
722 const gchar *cid = tny_mime_part_get_content_id (part);
723 const gchar *mime_type = tny_mime_part_get_content_type (part);
724 if ((cid != NULL)&&(mime_type != NULL)) {
725 TnyStream *stream = tny_mime_part_get_stream (part);
726 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type);
727 g_object_unref (stream);
729 if (pixbuf != NULL) {
730 /* wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf); */
731 g_object_unref (pixbuf);
738 update_last_cid (ModestMsgEditWindow *self, GList *attachments)
741 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
743 for (node = attachments; node != NULL; node = g_list_next (node)) {
744 TnyMimePart *part = (TnyMimePart *) node->data;
745 const gchar *cid = tny_mime_part_get_content_id (part);
747 char *invalid = NULL;
748 gint int_cid = strtol (cid, &invalid, 10);
749 if ((invalid != NULL) && (*invalid == '\0') && (int_cid > priv->last_cid)) {
750 priv->last_cid = int_cid;
758 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
761 const gchar *to, *cc, *bcc, *subject;
763 ModestMsgEditWindowPrivate *priv;
765 TnyHeaderFlags priority_flags;
766 TnyFolder *msg_folder;
767 gboolean is_html = FALSE;
769 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
770 g_return_if_fail (TNY_IS_MSG (msg));
772 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
774 header = tny_msg_get_header (msg);
775 to = tny_header_get_to (header);
776 cc = tny_header_get_cc (header);
777 bcc = tny_header_get_bcc (header);
778 subject = tny_header_get_subject (header);
779 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
782 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
784 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
785 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
786 gtk_widget_show (priv->cc_caption);
787 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
788 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
789 gtk_widget_hide (priv->cc_caption);
792 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
793 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
794 gtk_widget_show (priv->bcc_caption);
795 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
796 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
797 gtk_widget_hide (priv->bcc_caption);
800 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
801 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
804 update_window_title (self);
806 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
807 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
809 if ((body == NULL)||(body[0] == '\0')) {
811 body = modest_text_utils_convert_to_html ("");
814 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
815 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
818 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
821 if (preserve_is_rich && !is_html) {
822 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
823 /* Get the default format required from configuration */
824 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
825 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
828 /* Set the default focus depending on having already a To: field or not */
829 if ((!to)||(*to == '\0')) {
830 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
832 gtk_widget_grab_focus (priv->msg_body);
835 /* TODO: lower priority, select in the From: combo to the
836 value that comes from msg <- not sure, should it be
839 /* Add attachments to the view */
840 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
841 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
842 if (priv->attachments == NULL) {
843 gtk_widget_hide (priv->attachments_caption);
845 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
846 gtk_widget_show_all (priv->attachments_caption);
847 replace_with_attachments (self, priv->attachments);
849 update_last_cid (self, priv->attachments);
851 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
853 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
854 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
856 reset_modified (self);
858 update_dimmed (self);
859 text_buffer_can_undo (priv->text_buffer, FALSE, self);
860 text_buffer_can_redo (priv->text_buffer, FALSE, self);
863 g_free (priv->msg_uid);
864 priv->msg_uid = NULL;
867 /* we should set a reference to the incoming message if it is a draft */
868 msg_folder = tny_msg_get_folder (msg);
870 if (modest_tny_folder_is_local_folder (msg_folder)) {
871 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
872 if (type == TNY_FOLDER_TYPE_DRAFTS)
873 priv->draft_msg = g_object_ref(msg);
874 if (type == TNY_FOLDER_TYPE_OUTBOX)
875 priv->outbox_msg = g_object_ref(msg);
876 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
878 g_object_unref (msg_folder);
883 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
886 GList *item_children, *node;
887 GtkWidget *bin_child;
889 bin_child = gtk_bin_get_child (GTK_BIN(item));
891 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
893 for (node = item_children; node != NULL; node = g_list_next (node)) {
894 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
895 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
898 g_list_free (item_children);
902 menu_tool_button_dont_expand (GtkMenuToolButton *item)
905 GList *item_children, *node;
907 box = gtk_bin_get_child (GTK_BIN (item));
908 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
909 item_children = gtk_container_get_children (GTK_CONTAINER (box));
911 for (node = item_children; node != NULL; node = g_list_next (node)) {
912 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
913 if (GTK_IS_TOGGLE_BUTTON (node->data))
914 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
915 else if (GTK_IS_BUTTON (node->data))
916 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
918 g_list_free (item_children);
923 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
925 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
926 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
927 GtkWidget *placeholder;
928 GtkWidget *tool_item;
933 GtkWidget *sizes_menu;
934 GtkWidget *fonts_menu;
935 GSList *radio_group = NULL;
940 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
941 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
943 /* should we hide the toolbar? */
944 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
945 gtk_widget_hide (parent_priv->toolbar);
947 /* Font color placeholder */
948 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
949 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
952 tool_item = GTK_WIDGET (gtk_tool_item_new ());
953 priv->font_color_button = hildon_color_button_new ();
954 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
955 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
956 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
957 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
958 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
959 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
960 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
962 /* Font size and face placeholder */
963 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
964 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
966 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
967 priv->size_tool_button_label = gtk_label_new (NULL);
968 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
969 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
970 size_text,"</span>", NULL);
971 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
973 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
974 sizes_menu = gtk_menu_new ();
975 priv->size_items_group = NULL;
977 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
978 GtkWidget *size_menu_item;
980 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
981 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
982 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
983 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
984 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
985 gtk_widget_show (size_menu_item);
987 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
991 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
992 GtkWidget *item = (GtkWidget *) node->data;
993 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
997 priv->size_items_group = g_slist_reverse (priv->size_items_group);
998 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
999 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1000 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1001 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1002 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1003 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1004 priv->font_size_toolitem = tool_item;
1007 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1008 priv->font_tool_button_label = gtk_label_new (NULL);
1009 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1010 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1012 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1013 fonts_menu = gtk_menu_new ();
1014 priv->font_items_group = NULL;
1016 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1017 GtkWidget *font_menu_item;
1018 GtkWidget *child_label;
1020 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1021 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1022 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1023 wp_get_font_name (font_index), "</span>", NULL);
1024 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1027 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1028 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1029 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1030 gtk_widget_show (font_menu_item);
1032 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1035 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1036 GtkWidget *item = (GtkWidget *) node->data;
1037 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1040 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1041 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1042 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1043 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1044 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1045 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1046 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1047 priv->font_face_toolitem = tool_item;
1049 /* Set expand and homogeneous for remaining items */
1050 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1051 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1052 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1053 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1054 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1055 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1056 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1057 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1058 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1066 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1069 ModestWindowPrivate *parent_priv;
1070 ModestMsgEditWindowPrivate *priv;
1071 GtkActionGroup *action_group;
1072 GError *error = NULL;
1073 GdkPixbuf *window_icon = NULL;
1076 gboolean prefer_formatted;
1078 ModestPair *account_pair = NULL;
1080 g_return_val_if_fail (msg, NULL);
1081 g_return_val_if_fail (account_name, NULL);
1083 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
1085 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1086 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1088 parent_priv->ui_manager = gtk_ui_manager_new();
1089 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
1090 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1092 /* Add common actions */
1093 gtk_action_group_add_actions (action_group,
1094 modest_msg_edit_action_entries,
1095 G_N_ELEMENTS (modest_msg_edit_action_entries),
1097 gtk_action_group_add_toggle_actions (action_group,
1098 modest_msg_edit_toggle_action_entries,
1099 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
1101 gtk_action_group_add_radio_actions (action_group,
1102 modest_msg_edit_alignment_radio_action_entries,
1103 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
1105 G_CALLBACK (modest_ui_actions_on_change_justify),
1107 gtk_action_group_add_radio_actions (action_group,
1108 modest_msg_edit_zoom_action_entries,
1109 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
1111 G_CALLBACK (modest_ui_actions_on_change_zoom),
1113 gtk_action_group_add_radio_actions (action_group,
1114 modest_msg_edit_priority_action_entries,
1115 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
1117 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
1119 gtk_action_group_add_radio_actions (action_group,
1120 modest_msg_edit_file_format_action_entries,
1121 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
1122 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
1123 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
1125 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1126 g_object_unref (action_group);
1128 /* Load the UI definition */
1129 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
1131 if (error != NULL) {
1132 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
1133 g_clear_error (&error);
1136 /* Add accelerators */
1137 gtk_window_add_accel_group (GTK_WINDOW (obj),
1138 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1141 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
1142 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1145 init_window (MODEST_MSG_EDIT_WINDOW(obj));
1147 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1149 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1151 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1152 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1154 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
1156 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
1157 if (account_pair != NULL)
1158 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
1160 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1162 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1164 /* Set window icon */
1165 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
1167 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1168 g_object_unref (window_icon);
1171 /* Dim at start clipboard actions */
1172 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
1173 gtk_action_set_sensitive (action, FALSE);
1174 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
1175 gtk_action_set_sensitive (action, FALSE);
1176 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
1177 gtk_action_set_sensitive (action, FALSE);
1179 /* Update select all */
1180 update_select_all_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1181 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu");
1182 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (edit_menu_activated), obj);
1183 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu");
1184 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (view_menu_activated), obj);
1186 /* set initial state of cc and bcc */
1187 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
1188 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1189 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
1190 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
1191 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1192 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
1194 /* Setup the file format */
1195 conf = modest_runtime_get_conf ();
1196 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
1198 g_clear_error (&error);
1199 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
1201 file_format = (prefer_formatted) ?
1202 MODEST_FILE_FORMAT_FORMATTED_TEXT :
1203 MODEST_FILE_FORMAT_PLAIN_TEXT;
1204 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
1206 update_paste_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1207 priv->update_caption_visibility = TRUE;
1209 reset_modified (MODEST_MSG_EDIT_WINDOW (obj));
1211 return (ModestWindow*) obj;
1215 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1217 GString **string_buffer = (GString **) user_data;
1219 *string_buffer = g_string_append (*string_buffer, buffer);
1225 * @result: A new string which should be freed with g_free().
1228 get_formatted_data (ModestMsgEditWindow *edit_window)
1230 ModestMsgEditWindowPrivate *priv;
1231 GString *string_buffer = g_string_new ("");
1233 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1235 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1237 return g_string_free (string_buffer, FALSE);
1242 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1245 const gchar *account_name;
1246 ModestMsgEditWindowPrivate *priv;
1248 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1250 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1252 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1253 g_return_val_if_fail (account_name, NULL);
1256 /* don't free these (except from) */
1257 data = g_slice_new0 (MsgData);
1258 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1260 data->account_name = g_strdup (account_name);
1261 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1262 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1263 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1264 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1265 if (priv->draft_msg) {
1266 data->draft_msg = g_object_ref (priv->draft_msg);
1268 if (priv->outbox_msg) {
1269 data->draft_msg = g_object_ref (priv->outbox_msg);
1271 data->draft_msg = NULL;
1274 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1276 gtk_text_buffer_get_bounds (buf, &b, &e);
1277 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1279 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1280 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1282 data->html_body = NULL;
1284 /* deep-copy the data */
1285 GList *cursor = priv->attachments;
1286 data->attachments = NULL;
1288 if (!(TNY_IS_MIME_PART(cursor->data))) {
1289 g_warning ("strange data in attachment list");
1290 cursor = g_list_next (cursor);
1293 data->attachments = g_list_append (data->attachments,
1294 g_object_ref (cursor->data));
1295 cursor = g_list_next (cursor);
1298 data->priority_flags = priv->priority_flags;
1305 unref_gobject (GObject *obj, gpointer data)
1307 if (!G_IS_OBJECT(obj))
1309 g_object_unref (obj);
1313 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1316 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1324 g_free (data->subject);
1325 g_free (data->plain_body);
1326 g_free (data->html_body);
1327 g_free (data->account_name);
1329 if (data->draft_msg != NULL) {
1330 g_object_unref (data->draft_msg);
1331 data->draft_msg = NULL;
1334 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1335 g_list_free (data->attachments);
1337 g_slice_free (MsgData, data);
1341 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1344 ModestMsgEditWindowPrivate *priv = NULL;
1345 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1347 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1349 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1351 return MODEST_MSG_EDIT_FORMAT_HTML;
1353 return MODEST_MSG_EDIT_FORMAT_TEXT;
1357 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1358 ModestMsgEditFormat format)
1360 ModestMsgEditWindowPrivate *priv;
1362 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1363 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1366 case MODEST_MSG_EDIT_FORMAT_HTML:
1367 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1369 case MODEST_MSG_EDIT_FORMAT_TEXT:
1370 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1373 g_return_if_reached ();
1377 ModestMsgEditFormatState *
1378 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1380 ModestMsgEditFormatState *format_state = NULL;
1381 ModestMsgEditWindowPrivate *priv;
1382 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1384 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1385 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1387 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1389 format_state = g_new0 (ModestMsgEditFormatState, 1);
1390 format_state->bold = buffer_format->bold&0x1;
1391 format_state->italics = buffer_format->italic&0x1;
1392 format_state->bullet = buffer_format->bullet&0x1;
1393 format_state->color = buffer_format->color;
1394 format_state->font_size = buffer_format->font_size;
1395 format_state->font_family = wp_get_font_name (buffer_format->font);
1396 format_state->justification = buffer_format->justification;
1397 g_free (buffer_format);
1399 return format_state;
1404 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1405 const ModestMsgEditFormatState *format_state)
1407 ModestMsgEditWindowPrivate *priv;
1408 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1409 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1410 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1411 g_return_if_fail (format_state != NULL);
1413 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1414 gtk_widget_grab_focus (priv->msg_body);
1415 buffer_format->bold = (format_state->bold != FALSE);
1416 buffer_format->italic = (format_state->italics != FALSE);
1417 buffer_format->color = format_state->color;
1418 buffer_format->font_size = format_state->font_size;
1419 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1420 buffer_format->justification = format_state->justification;
1421 buffer_format->bullet = format_state->bullet;
1423 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1425 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1426 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1427 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1428 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1429 buffer_format->cs.font = (buffer_format->font != current_format->font);
1430 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1431 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1433 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1434 if (buffer_format->cs.bold) {
1435 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1437 if (buffer_format->cs.italic) {
1438 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1440 if (buffer_format->cs.color) {
1441 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1443 if (buffer_format->cs.font_size) {
1444 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1446 if (buffer_format->cs.justification) {
1447 switch (buffer_format->justification) {
1448 case GTK_JUSTIFY_LEFT:
1449 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1451 case GTK_JUSTIFY_CENTER:
1452 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1454 case GTK_JUSTIFY_RIGHT:
1455 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1462 if (buffer_format->cs.font) {
1463 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1465 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1466 if (buffer_format->cs.bullet) {
1467 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((buffer_format->bullet)?1:0));
1469 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1471 g_free (current_format);
1476 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1478 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1480 ModestWindowPrivate *parent_priv;
1481 ModestMsgEditWindowPrivate *priv;
1482 GtkWidget *new_size_menuitem;
1483 GtkWidget *new_font_menuitem;
1485 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1486 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1488 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1489 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1490 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1491 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1493 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1494 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1495 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1498 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1500 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1501 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1503 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1504 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1506 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1507 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1509 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1510 G_CALLBACK (modest_msg_edit_window_color_button_change),
1512 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1513 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1514 G_CALLBACK (modest_msg_edit_window_color_button_change),
1517 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1518 buffer_format->font_size))->data);
1519 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1523 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1524 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1525 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1527 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1528 G_CALLBACK (modest_msg_edit_window_size_change),
1530 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1531 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1532 G_CALLBACK (modest_msg_edit_window_size_change),
1536 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1537 buffer_format->font))->data);
1538 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1542 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1543 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1544 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1546 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1547 G_CALLBACK (modest_msg_edit_window_font_change),
1549 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1550 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1551 G_CALLBACK (modest_msg_edit_window_font_change),
1555 g_free (buffer_format);
1561 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1564 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1565 ModestMsgEditWindowPrivate *priv;
1566 GtkWidget *dialog = NULL;
1568 const GdkColor *new_color = NULL;
1570 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1571 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1573 #ifdef MODEST_HILDON_VERSION_0
1574 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1575 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1577 dialog = hildon_color_chooser_new ();
1578 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1579 #endif /*MODEST_HILDON_VERSION_0*/
1580 g_free (buffer_format);
1582 response = gtk_dialog_run (GTK_DIALOG (dialog));
1584 case GTK_RESPONSE_OK: {
1585 #ifdef MODEST_HILDON_VERSION_0
1586 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1589 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1591 #endif /*MODEST_HILDON_VERSION_0*/
1598 gtk_widget_destroy (dialog);
1600 if (new_color != NULL)
1601 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1606 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1609 ModestMsgEditWindowPrivate *priv;
1610 GtkWidget *dialog = NULL;
1612 GdkColor *old_color = NULL;
1613 const GdkColor *new_color = NULL;
1615 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1616 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1618 #ifdef MODEST_HILDON_VERSION_0
1619 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1620 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1622 dialog = hildon_color_chooser_new ();
1623 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1624 #endif /*MODEST_HILDON_VERSION_9*/
1626 response = gtk_dialog_run (GTK_DIALOG (dialog));
1628 case GTK_RESPONSE_OK: {
1629 #ifdef MODEST_HILDON_VERSION_0
1630 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1633 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1635 #endif /*MODEST_HILDON_VERSION_0*/
1641 gtk_widget_destroy (dialog);
1643 if (new_color != NULL)
1644 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1648 static TnyStream* create_stream_for_uri (const gchar* uri)
1653 TnyStream *result = NULL;
1655 GnomeVFSHandle *handle = NULL;
1656 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1657 if (test == GNOME_VFS_OK) {
1658 /* Create the tinymail stream: */
1659 /* Presumably tinymai will call gnome_vfs_close (handle) later. */
1660 result = TNY_STREAM (tny_vfs_stream_new (handle));
1667 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1670 ModestMsgEditWindowPrivate *priv;
1671 GtkWidget *dialog = NULL;
1673 GSList *uris = NULL;
1674 GSList *uri_node = NULL;
1676 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1678 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1679 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1680 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1682 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1684 response = gtk_dialog_run (GTK_DIALOG (dialog));
1686 case GTK_RESPONSE_OK:
1687 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1692 gtk_widget_destroy (dialog);
1694 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1696 GnomeVFSHandle *handle = NULL;
1697 GnomeVFSResult result;
1698 GtkTextIter position;
1699 GtkTextMark *insert_mark;
1701 uri = (const gchar *) uri_node->data;
1702 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1703 if (result == GNOME_VFS_OK) {
1705 GnomeVFSFileInfo info;
1706 gchar *filename, *basename, *escaped_filename;
1707 TnyMimePart *mime_part;
1709 const gchar *mime_type = NULL;
1710 GnomeVFSURI *vfs_uri;
1712 vfs_uri = gnome_vfs_uri_new (uri);
1714 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1715 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1716 g_free (escaped_filename);
1717 gnome_vfs_uri_unref (vfs_uri);
1719 if (gnome_vfs_get_file_info (uri, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
1720 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1722 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1724 mime_part = tny_platform_factory_new_mime_part
1725 (modest_runtime_get_platform_factory ());
1727 TnyStream *stream = create_stream_for_uri (uri);
1728 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1730 content_id = g_strdup_printf ("%d", priv->last_cid);
1731 tny_mime_part_set_content_id (mime_part, content_id);
1732 g_free (content_id);
1735 basename = g_path_get_basename (filename);
1736 tny_mime_part_set_filename (mime_part, basename);
1739 pixbuf = pixbuf_from_stream (stream, mime_type);
1741 if (pixbuf != NULL) {
1742 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1743 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1744 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1747 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1748 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1750 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1751 gtk_widget_show_all (priv->attachments_caption);
1752 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1762 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
1765 ModestMsgEditWindowPrivate *priv;
1766 GtkWidget *dialog = NULL;
1768 GSList *uris = NULL;
1771 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1773 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1774 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
1775 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1777 response = gtk_dialog_run (GTK_DIALOG (dialog));
1779 case GTK_RESPONSE_OK:
1780 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1785 gtk_widget_destroy (dialog);
1787 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1788 const gchar *uri = (const gchar *) uri_node->data;
1789 modest_msg_edit_window_attach_file_one (window, uri);
1791 g_slist_foreach (uris, (GFunc) g_free, NULL);
1792 g_slist_free (uris);
1796 modest_msg_edit_window_attach_file_one (
1797 ModestMsgEditWindow *window,
1800 g_return_if_fail (window);
1801 g_return_if_fail (uri);
1803 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1806 GnomeVFSHandle *handle = NULL;
1807 GnomeVFSResult result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1808 if (result == GNOME_VFS_OK) {
1809 TnyMimePart *mime_part;
1811 const gchar *mime_type = NULL;
1813 gchar *escaped_filename;
1816 GnomeVFSFileInfo info;
1817 GnomeVFSURI *vfs_uri;
1819 vfs_uri = gnome_vfs_uri_new (uri);
1822 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1823 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1824 g_free (escaped_filename);
1825 gnome_vfs_uri_unref (vfs_uri);
1827 if (gnome_vfs_get_file_info (uri,
1829 GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
1830 GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1832 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1833 mime_part = tny_platform_factory_new_mime_part
1834 (modest_runtime_get_platform_factory ());
1835 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1837 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1839 content_id = g_strdup_printf ("%d", priv->last_cid);
1840 tny_mime_part_set_content_id (mime_part, content_id);
1841 g_free (content_id);
1844 basename = g_path_get_basename (filename);
1845 tny_mime_part_set_filename (mime_part, basename);
1848 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1849 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1851 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1852 gtk_widget_show_all (priv->attachments_caption);
1853 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1859 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1862 ModestMsgEditWindowPrivate *priv;
1863 gboolean clean_list = FALSE;
1865 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1866 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1868 if (att_list == NULL) {
1869 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1873 if (att_list == NULL) {
1874 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1876 GtkWidget *confirmation_dialog = NULL;
1877 gboolean dialog_response;
1879 gchar *message = NULL;
1880 const gchar *filename = NULL;
1882 if (att_list->next == NULL) {
1883 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1887 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1888 att_list->next == NULL), filename);
1889 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1891 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1892 gtk_widget_destroy (confirmation_dialog);
1893 if (!dialog_response) {
1895 g_list_free (att_list);
1898 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1900 for (node = att_list; node != NULL; node = g_list_next (node)) {
1901 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1902 const gchar *att_id;
1903 priv->attachments = g_list_remove (priv->attachments, mime_part);
1905 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1907 if (priv->attachments == NULL)
1908 gtk_widget_hide (priv->attachments_caption);
1909 att_id = tny_mime_part_get_content_id (mime_part);
1911 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1913 g_object_unref (mime_part);
1914 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1919 g_list_free (att_list);
1923 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1926 ModestMsgEditWindowPrivate *priv;
1927 GdkColor *new_color;
1928 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1930 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1931 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1934 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1936 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1938 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1940 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1945 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1948 ModestMsgEditWindowPrivate *priv;
1949 gint new_size_index;
1950 ModestMsgEditWindow *window;
1953 window = MODEST_MSG_EDIT_WINDOW (userdata);
1954 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1955 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1957 if (gtk_check_menu_item_get_active (menu_item)) {
1959 WPTextBufferFormat format;
1961 memset (&format, 0, sizeof (format));
1962 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1964 label = gtk_bin_get_child (GTK_BIN (menu_item));
1966 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1967 format.cs.font_size = TRUE;
1968 format.cs.text_position = TRUE;
1969 format.cs.font = TRUE;
1970 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1971 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1973 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1974 (gpointer) wp_get_font_size_index (new_size_index, 12)))
1975 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1977 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1978 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1979 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1985 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1988 ModestMsgEditWindowPrivate *priv;
1989 gint new_font_index;
1990 ModestMsgEditWindow *window;
1993 window = MODEST_MSG_EDIT_WINDOW (userdata);
1994 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1995 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1997 if (gtk_check_menu_item_get_active (menu_item)) {
2000 label = gtk_bin_get_child (GTK_BIN (menu_item));
2002 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2004 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2005 (gpointer) new_font_index))
2006 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2008 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2009 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2010 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2016 modest_msg_edit_window_set_zoom (ModestWindow *window,
2019 ModestMsgEditWindowPrivate *priv;
2020 ModestWindowPrivate *parent_priv;
2021 GtkRadioAction *zoom_radio_action;
2023 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2025 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2026 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2027 priv->zoom_level = zoom;
2028 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom*DEFAULT_FONT_SCALE);
2030 /* Zoom level menu options should be updated with the current zoom level */
2031 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2032 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2033 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2034 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2035 /* FIXME: Not availible before Gtk 2.10 */
2037 gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
2042 modest_msg_edit_window_get_zoom (ModestWindow *window)
2044 ModestMsgEditWindowPrivate *priv;
2046 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
2048 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2049 return priv->zoom_level;
2053 zoom_allowed (ModestMsgEditWindow *window)
2057 focus = gtk_window_get_focus (GTK_WINDOW (window));
2058 return (focus != NULL && WP_IS_TEXT_VIEW (focus));
2062 modest_msg_edit_window_zoom_plus (ModestWindow *window)
2064 ModestWindowPrivate *parent_priv;
2065 GtkRadioAction *zoom_radio_action;
2066 GSList *group, *node;
2068 /* First we check if the text view is focused. If not, zooming is not allowed */
2069 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2070 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2074 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2075 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2076 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2078 group = gtk_radio_action_get_group (zoom_radio_action);
2080 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
2081 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
2085 for (node = group; node != NULL; node = g_slist_next (node)) {
2086 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
2087 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
2095 modest_msg_edit_window_zoom_minus (ModestWindow *window)
2097 ModestWindowPrivate *parent_priv;
2098 GtkRadioAction *zoom_radio_action;
2099 GSList *group, *node;
2101 /* First we check if the text view is focused. If not, zooming is not allowed */
2102 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2103 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2107 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2108 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2109 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2111 group = gtk_radio_action_get_group (zoom_radio_action);
2113 for (node = group; node != NULL; node = g_slist_next (node)) {
2114 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
2115 if (node->next != NULL) {
2116 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
2119 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
2127 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2129 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2130 ModestWindowPrivate *parent_priv;
2131 ModestWindowMgr *mgr;
2132 gboolean is_fullscreen;
2133 GtkAction *fs_toggle_action;
2136 mgr = modest_runtime_get_window_mgr ();
2137 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2139 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2141 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2142 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2143 if (is_fullscreen != active)
2144 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2152 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
2154 ModestWindowPrivate *parent_priv;
2155 GtkAction *fs_toggle_action;
2158 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2160 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2161 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
2162 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
2166 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2169 ModestMsgEditWindowPrivate *priv = NULL;
2170 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2172 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2173 if (!priv->update_caption_visibility)
2176 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2178 gtk_widget_show (priv->cc_caption);
2180 gtk_widget_hide (priv->cc_caption);
2182 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2186 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2189 ModestMsgEditWindowPrivate *priv = NULL;
2190 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2192 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2193 if (!priv->update_caption_visibility)
2196 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2198 gtk_widget_show (priv->bcc_caption);
2200 gtk_widget_hide (priv->bcc_caption);
2202 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2206 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2207 ModestRecptEditor *editor)
2209 ModestMsgEditWindowPrivate *priv;
2211 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2212 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2213 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2215 if (editor == NULL) {
2216 GtkWidget *view_focus;
2217 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2219 /* This code should be kept in sync with ModestRecptEditor. The
2220 textview inside the recpt editor is the one that really gets the
2221 focus. As it's inside a scrolled window, and this one inside the
2222 hbox recpt editor inherits from, we'll need to go up in the
2223 hierarchy to know if the text view is part of the recpt editor
2224 or if it's a different text entry */
2226 if (gtk_widget_get_parent (view_focus)) {
2227 GtkWidget *first_parent;
2229 first_parent = gtk_widget_get_parent (view_focus);
2230 if (gtk_widget_get_parent (first_parent) &&
2231 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2232 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2237 editor = MODEST_RECPT_EDITOR (priv->to_field);
2241 modest_address_book_select_addresses (editor);
2246 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2248 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2250 modest_msg_edit_window_open_addressbook (window, NULL);
2254 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2255 gboolean show_toolbar)
2257 ModestWindowPrivate *parent_priv;
2259 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2260 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2262 /* FIXME: we can not just use the code of
2263 modest_msg_edit_window_setup_toolbar because it has a
2264 mixture of both initialization and creation code. */
2267 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2269 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2273 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2274 TnyHeaderFlags priority_flags)
2276 ModestMsgEditWindowPrivate *priv;
2277 ModestWindowPrivate *parent_priv;
2279 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2281 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2282 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2283 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2285 if (priv->priority_flags != priority_flags) {
2286 GtkAction *priority_action = NULL;
2288 priv->priority_flags = priority_flags;
2290 switch (priority_flags) {
2291 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2292 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2293 gtk_widget_show (priv->priority_icon);
2294 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2295 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2297 case TNY_HEADER_FLAG_LOW_PRIORITY:
2298 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2299 gtk_widget_show (priv->priority_icon);
2300 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2301 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2304 gtk_widget_hide (priv->priority_icon);
2305 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2306 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2309 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2310 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2315 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2318 ModestMsgEditWindowPrivate *priv;
2319 ModestWindowPrivate *parent_priv;
2320 gint current_format;
2322 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2324 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2325 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2327 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2328 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2330 if (current_format != file_format) {
2331 switch (file_format) {
2332 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2333 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2335 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2339 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2340 response = gtk_dialog_run (GTK_DIALOG (dialog));
2341 gtk_widget_destroy (dialog);
2342 if (response == GTK_RESPONSE_OK) {
2343 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2345 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2346 modest_maemo_toggle_action_set_active_block_notify (action, TRUE);
2351 update_dimmed (window);
2356 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2359 ModestMsgEditWindowPrivate *priv;
2360 WPTextBufferFormat oldfmt, fmt;
2361 gint old_position = 0;
2365 GdkColor *color = NULL;
2366 gboolean bold, bold_set, italic, italic_set;
2367 gboolean underline, underline_set;
2368 gboolean strikethrough, strikethrough_set;
2369 gboolean position_set;
2370 gboolean font_size_set, font_set, color_set;
2373 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2374 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2376 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2378 /* First we get the currently selected font information */
2379 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2380 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2382 switch (oldfmt.text_position) {
2383 case TEXT_POSITION_NORMAL:
2386 case TEXT_POSITION_SUPERSCRIPT:
2394 g_object_set (G_OBJECT (dialog),
2395 "bold", oldfmt.bold != FALSE,
2396 "bold-set", !oldfmt.cs.bold,
2397 "underline", oldfmt.underline != FALSE,
2398 "underline-set", !oldfmt.cs.underline,
2399 "italic", oldfmt.italic != FALSE,
2400 "italic-set", !oldfmt.cs.italic,
2401 "strikethrough", oldfmt.strikethrough != FALSE,
2402 "strikethrough-set", !oldfmt.cs.strikethrough,
2403 "color", &oldfmt.color,
2404 "color-set", !oldfmt.cs.color,
2405 "size", wp_font_size[oldfmt.font_size],
2406 "size-set", !oldfmt.cs.font_size,
2407 "position", old_position,
2408 "position-set", !oldfmt.cs.text_position,
2409 "family", wp_get_font_name (oldfmt.font),
2410 "family-set", !oldfmt.cs.font,
2413 gtk_widget_show_all (dialog);
2414 response = gtk_dialog_run (GTK_DIALOG (dialog));
2415 if (response == GTK_RESPONSE_OK) {
2417 g_object_get( dialog,
2419 "bold-set", &bold_set,
2420 "underline", &underline,
2421 "underline-set", &underline_set,
2423 "italic-set", &italic_set,
2424 "strikethrough", &strikethrough,
2425 "strikethrough-set", &strikethrough_set,
2427 "color-set", &color_set,
2429 "size-set", &font_size_set,
2430 "family", &font_name,
2431 "family-set", &font_set,
2432 "position", &position,
2433 "position-set", &position_set,
2438 if (response == GTK_RESPONSE_OK) {
2439 memset(&fmt, 0, sizeof(fmt));
2445 fmt.italic = italic;
2446 fmt.cs.italic = TRUE;
2448 if (underline_set) {
2449 fmt.underline = underline;
2450 fmt.cs.underline = TRUE;
2452 if (strikethrough_set) {
2453 fmt.strikethrough = strikethrough;
2454 fmt.cs.strikethrough = TRUE;
2459 ? TEXT_POSITION_NORMAL
2460 : ( ( position == 1 )
2461 ? TEXT_POSITION_SUPERSCRIPT
2462 : TEXT_POSITION_SUBSCRIPT );
2463 fmt.cs.text_position = TRUE;
2467 fmt.cs.color = TRUE;
2470 fmt.font = wp_get_font_index(font_name,
2475 if (font_size_set) {
2476 fmt.font_size = wp_get_font_size_index(
2477 font_size, DEFAULT_FONT_SIZE);
2478 fmt.cs.font_size = TRUE;
2480 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2482 gtk_widget_destroy (dialog);
2484 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2488 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2490 ModestMsgEditWindowPrivate *priv;
2492 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2493 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2495 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2497 update_dimmed (window);
2502 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2504 ModestMsgEditWindowPrivate *priv;
2506 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2507 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2509 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2511 update_dimmed (window);
2516 update_dimmed (ModestMsgEditWindow *window)
2518 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2519 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2523 gboolean editor_focused;
2525 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2526 editor_focused = gtk_widget_is_focus (priv->msg_body);
2528 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2529 gtk_action_set_sensitive (action, rich_text && editor_focused);
2530 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2531 gtk_action_set_sensitive (action, rich_text && editor_focused);
2532 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2533 gtk_action_set_sensitive (action, rich_text && editor_focused);
2534 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2535 gtk_action_set_sensitive (action, rich_text && editor_focused);
2536 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2537 gtk_action_set_sensitive (action, rich_text && editor_focused);
2538 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2539 gtk_action_set_sensitive (action, rich_text && editor_focused);
2540 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2541 gtk_action_set_sensitive (action, rich_text && editor_focused);
2542 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2543 gtk_action_set_sensitive (action, rich_text && editor_focused);
2544 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2545 gtk_action_set_sensitive (action, rich_text && editor_focused);
2546 widget = priv->font_color_button;
2547 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2548 widget = priv->font_size_toolitem;
2549 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2550 widget = priv->font_face_toolitem;
2551 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2555 setup_insensitive_handlers (ModestMsgEditWindow *window)
2557 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2558 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2561 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2562 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2563 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2564 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2565 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2566 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2567 widget = priv->font_color_button;
2568 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2569 widget = priv->font_size_toolitem;
2570 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2571 widget = priv->font_face_toolitem;
2572 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2577 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2579 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2582 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2583 gtk_action_set_sensitive (action, can_undo);
2587 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2589 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2592 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/RedoMenu");
2593 gtk_action_set_sensitive (action, can_redo);
2597 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2600 GtkTextIter match_start, match_end;
2602 if (image_id == NULL)
2605 gtk_text_buffer_get_start_iter (buffer, &iter);
2607 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2608 GSList *tags = gtk_text_iter_get_tags (&match_start);
2610 for (node = tags; node != NULL; node = g_slist_next (node)) {
2611 GtkTextTag *tag = (GtkTextTag *) node->data;
2612 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2613 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2614 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2616 offset = gtk_text_iter_get_offset (&match_start);
2617 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2618 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2622 gtk_text_iter_forward_char (&iter);
2627 msg_body_focus (GtkWidget *focus,
2628 GdkEventFocus *event,
2632 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2637 recpt_field_changed (GtkTextBuffer *buffer,
2638 ModestMsgEditWindow *editor)
2640 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2641 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2642 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2643 gboolean dim = FALSE;
2646 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2647 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2648 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2650 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2651 gtk_text_buffer_get_char_count (cc_buffer) +
2652 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2654 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2655 gtk_action_set_sensitive (action, !dim);
2656 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2657 gtk_action_set_sensitive (action, !dim);
2661 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2663 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2667 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2669 gboolean rich_text, editor_focused;
2671 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2672 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2673 editor_focused = gtk_widget_is_focus (priv->msg_body);
2676 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2677 else if (!editor_focused)
2678 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2682 reset_modified (ModestMsgEditWindow *editor)
2684 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2685 GtkTextBuffer *buffer;
2687 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2688 gtk_text_buffer_set_modified (buffer, FALSE);
2689 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2690 gtk_text_buffer_set_modified (buffer, FALSE);
2691 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2692 gtk_text_buffer_set_modified (buffer, FALSE);
2693 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2697 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2699 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2700 GtkTextBuffer *buffer;
2702 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2703 if (gtk_text_buffer_get_modified (buffer))
2705 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2706 if (gtk_text_buffer_get_modified (buffer))
2708 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2709 if (gtk_text_buffer_get_modified (buffer))
2711 if (gtk_text_buffer_get_modified (priv->text_buffer))
2718 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
2720 ModestMsgEditWindowPrivate *priv = NULL;
2722 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2723 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2725 /* check if there's no recipient added */
2726 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2727 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2728 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2729 /* no recipient contents, then select contacts */
2730 modest_msg_edit_window_open_addressbook (window, NULL);
2734 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook))
2736 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook))
2738 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook))
2741 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2748 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2749 ModestMsgEditWindow *window)
2751 modest_msg_edit_window_offer_attach_file (window);
2755 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2757 ModestMsgEditWindow *window)
2759 ModestWindowPrivate *parent_priv;
2760 ModestMsgEditWindowPrivate *priv;
2762 gboolean has_selection;
2764 GList *selected_attachments = NULL;
2765 gint n_att_selected = 0;
2767 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2768 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2770 if (!GTK_WIDGET_VISIBLE (window))
2772 has_selection = gtk_clipboard_wait_for_targets (clipboard, NULL, NULL);
2773 focused = gtk_window_get_focus (GTK_WINDOW (window));
2775 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2776 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2777 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2778 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2780 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2781 n_att_selected = g_list_length (selected_attachments);
2782 g_list_free (selected_attachments);
2784 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2785 gtk_action_set_sensitive (action, n_att_selected == 1);
2787 update_paste_dimming (window);
2791 update_window_title (ModestMsgEditWindow *window)
2793 ModestMsgEditWindowPrivate *priv = NULL;
2794 const gchar *subject;
2796 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2797 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2798 if (subject == NULL || subject[0] == '\0')
2799 subject = _("mail_va_new_email");
2801 gtk_window_set_title (GTK_WINDOW (window), subject);
2806 subject_field_changed (GtkEditable *editable,
2807 ModestMsgEditWindow *window)
2809 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2810 update_window_title (window);
2811 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2815 message_is_empty (ModestMsgEditWindow *window)
2817 ModestMsgEditWindowPrivate *priv = NULL;
2819 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2820 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2822 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
2823 * so we can ignore markup.
2825 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
2828 count = gtk_text_buffer_get_char_count (buf);
2834 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2837 ModestMsgEditWindowPrivate *priv = NULL;
2839 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2840 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2842 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2845 gtk_widget_show_all (priv->find_toolbar);
2846 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2848 gtk_widget_hide_all (priv->find_toolbar);
2849 gtk_widget_grab_focus (priv->msg_body);
2855 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2857 GtkTextIter *match_start,
2858 GtkTextIter *match_end)
2860 GtkTextIter end_iter;
2861 gchar *str_casefold;
2864 gchar *range_casefold;
2867 gboolean result = FALSE;
2874 gtk_text_iter_forward_to_end (&end_iter);
2876 str_casefold = g_utf8_casefold (str, -1);
2877 str_chars_n = strlen (str);
2879 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2880 range_casefold = g_utf8_casefold (range_text, -1);
2881 range_chars_n = strlen (range_casefold);
2883 if (range_chars_n < str_chars_n) {
2884 g_free (str_casefold);
2885 g_free (range_text);
2886 g_free (range_casefold);
2890 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2891 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2892 if (!g_utf8_collate (range_subtext, str_casefold)) {
2893 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2895 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2896 match_start, match_end, NULL);
2897 g_free (found_text);
2899 g_free (range_subtext);
2903 g_free (str_casefold);
2904 g_free (range_text);
2905 g_free (range_casefold);
2912 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2913 ModestMsgEditWindow *window)
2915 gchar *current_search = NULL;
2916 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2918 GtkTextIter selection_start, selection_end;
2919 GtkTextIter match_start, match_end;
2920 gboolean continue_search = FALSE;
2922 if (message_is_empty (window)) {
2923 g_free (priv->last_search);
2924 priv->last_search = NULL;
2925 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
2929 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2930 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2931 g_free (current_search);
2932 g_free (priv->last_search);
2933 priv->last_search = NULL;
2934 /* Information banner about empty search */
2935 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2939 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2940 continue_search = TRUE;
2942 g_free (priv->last_search);
2943 priv->last_search = g_strdup (current_search);
2946 if (continue_search) {
2947 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2948 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2949 &match_start, &match_end);
2951 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2953 GtkTextIter buffer_start;
2954 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2955 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2956 &match_start, &match_end);
2958 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2961 /* Mark as selected the string found in search */
2963 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2964 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2966 g_free (priv->last_search);
2967 priv->last_search = NULL;
2969 g_free (current_search);
2973 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2974 ModestMsgEditWindow *window)
2976 GtkToggleAction *toggle;
2977 ModestWindowPrivate *parent_priv;
2978 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2980 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2981 gtk_toggle_action_set_active (toggle, FALSE);
2986 update_paste_dimming (ModestMsgEditWindow *window)
2988 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2989 GtkAction *action = NULL;
2990 GtkClipboard *clipboard = NULL;
2991 ModestEmailClipboard *e_clipboard;
2995 focused = gtk_window_get_focus (GTK_WINDOW (window));
2997 e_clipboard = modest_runtime_get_email_clipboard ();
2998 if (!modest_email_clipboard_cleared (e_clipboard)) {
3001 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3002 active = gtk_clipboard_wait_is_text_available (clipboard);
3006 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
3010 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
3011 gtk_action_set_sensitive (action, active);
3016 update_select_all_dimming (ModestMsgEditWindow *window)
3019 gboolean dimmed = FALSE;
3021 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3023 focused = gtk_window_get_focus (GTK_WINDOW (window));
3024 if (GTK_IS_ENTRY (focused)) {
3025 const gchar *current_text;
3026 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
3027 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
3028 } else if (GTK_IS_TEXT_VIEW (focused)) {
3029 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
3030 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
3031 } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
3034 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
3035 gtk_action_set_sensitive (action, !dimmed);
3039 update_zoom_dimming (ModestMsgEditWindow *window)
3042 gboolean dimmed = FALSE;
3044 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3046 focused = gtk_window_get_focus (GTK_WINDOW (window));
3047 dimmed = ! WP_IS_TEXT_VIEW (focused);
3048 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
3049 gtk_action_set_sensitive (action, !dimmed);
3053 edit_menu_activated (GtkAction *action,
3056 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3058 update_select_all_dimming (window);
3059 update_paste_dimming (window);
3062 view_menu_activated (GtkAction *action,
3065 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3067 update_zoom_dimming (window);
3071 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3073 ModestMsgEditWindowPrivate *priv;
3075 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3080 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3083 ModestMsgEditWindowPrivate *priv;
3085 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3091 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3094 ModestMsgEditWindowPrivate *priv;
3095 TnyHeader *header = NULL;
3097 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3098 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3100 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3101 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3103 if (priv->draft_msg != NULL) {
3104 header = tny_msg_get_header (priv->draft_msg);
3105 if (TNY_IS_HEADER (header)) {
3106 modest_window_mgr_unregister_header (mgr, header);
3108 g_object_unref (priv->draft_msg);
3111 if (draft != NULL) {
3112 g_object_ref (draft);
3113 header = tny_msg_get_header (draft);
3114 if (TNY_IS_HEADER (header))
3115 modest_window_mgr_register_header (mgr, header);
3116 if (priv->msg_uid) {
3117 g_free (priv->msg_uid);
3118 priv->msg_uid = NULL;
3120 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3123 priv->draft_msg = draft;
3127 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3128 GtkTextIter *start, GtkTextIter *end,
3131 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3132 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3135 if (tag == NULL+13) return;
3136 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3137 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3138 replace_with_attachments (window, priv->attachments);
3143 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3146 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3148 g_return_if_fail (TNY_IS_MIME_PART (part));
3149 priv->attachments = g_list_prepend (priv->attachments, part);
3150 g_object_ref (part);
3151 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part);
3152 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3153 gtk_widget_show_all (priv->attachments_caption);
3154 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3158 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3160 ModestMsgEditWindowPrivate *priv;
3162 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3163 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3165 return priv->msg_uid;