1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
41 #include <modest-account-mgr.h>
42 #include <modest-account-mgr-helpers.h>
44 #include <widgets/modest-msg-edit-window.h>
45 #include <widgets/modest-combo-box.h>
46 #include <widgets/modest-recpt-editor.h>
47 #include <widgets/modest-attachments-view.h>
49 #include <modest-runtime.h>
51 #include "modest-platform.h"
52 #include "modest-icon-names.h"
53 #include "modest-widget-memory.h"
54 #include "modest-window-priv.h"
55 #include "modest-mail-operation.h"
56 #include "modest-tny-platform-factory.h"
57 #include "modest-tny-msg.h"
58 #include "modest-tny-folder.h"
59 #include "modest-address-book.h"
60 #include "modest-text-utils.h"
61 #include <tny-simple-list.h>
62 #include <wptextview.h>
63 #include <wptextbuffer.h>
64 #include "modest-scroll-area.h"
66 #include "modest-hildon-includes.h"
67 #ifdef MODEST_HAVE_HILDON0_WIDGETS
68 #include <hildon-widgets/hildon-color-chooser.h>
70 #include "widgets/modest-msg-edit-window-ui.h"
71 #ifdef MODEST_HAVE_HILDON0_WIDGETS
72 #include <libgnomevfs/gnome-vfs-mime-utils.h>
74 #include <libgnomevfs/gnome-vfs-mime.h>
76 #include "modest-maemo-utils.h"
79 #define DEFAULT_FONT_SIZE 3
80 #define DEFAULT_FONT 2
81 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
82 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
83 #define DEFAULT_MAIN_VBOX_SPACING 6
84 #define SUBJECT_MAX_LENGTH 1000
85 #define IMAGE_MAX_WIDTH 608
86 #define DEFAULT_FONT_SCALE 1.5
88 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
89 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
90 static void modest_msg_edit_window_finalize (GObject *obj);
92 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
93 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
94 static void send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
95 static void style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
96 static void setup_insensitive_handlers (ModestMsgEditWindow *editor);
97 static void reset_modified (ModestMsgEditWindow *editor);
99 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
100 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
101 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
102 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
103 GtkTextIter *start, GtkTextIter *end,
105 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
106 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
107 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
109 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
111 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
113 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
114 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
115 GdkEventWindowState *event,
117 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
118 ModestRecptEditor *editor);
119 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
120 ModestMsgEditWindow *window);
122 /* ModestWindow methods implementation */
123 static void modest_msg_edit_window_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;
246 TnyHeaderFlags priority_flags;
250 gulong clipboard_change_handler_id;
257 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
258 MODEST_TYPE_MSG_EDIT_WINDOW, \
259 ModestMsgEditWindowPrivate))
261 static GtkWindowClass *parent_class = NULL;
263 /* uncomment the following if you have defined any signals */
264 /* static guint signals[LAST_SIGNAL] = {0}; */
267 modest_msg_edit_window_get_type (void)
269 static GType my_type = 0;
271 static const GTypeInfo my_info = {
272 sizeof(ModestMsgEditWindowClass),
273 NULL, /* base init */
274 NULL, /* base finalize */
275 (GClassInitFunc) modest_msg_edit_window_class_init,
276 NULL, /* class finalize */
277 NULL, /* class data */
278 sizeof(ModestMsgEditWindow),
280 (GInstanceInitFunc) modest_msg_edit_window_init,
283 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
284 "ModestMsgEditWindow",
287 wp_text_buffer_library_init ();
293 save_state (ModestWindow *self)
295 modest_widget_memory_save (modest_runtime_get_conf(),
296 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
301 restore_settings (ModestMsgEditWindow *self)
303 modest_widget_memory_restore (modest_runtime_get_conf(),
304 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
309 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
311 GObjectClass *gobject_class;
312 ModestWindowClass *modest_window_class;
313 gobject_class = (GObjectClass*) klass;
314 modest_window_class = (ModestWindowClass*) klass;
316 parent_class = g_type_class_peek_parent (klass);
317 gobject_class->finalize = modest_msg_edit_window_finalize;
319 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
320 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
321 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
322 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
323 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
324 modest_window_class->save_state_func = save_state;
325 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
327 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
331 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
333 ModestMsgEditWindowPrivate *priv;
334 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
336 priv->msg_body = NULL;
337 priv->from_field = NULL;
338 priv->to_field = NULL;
339 priv->cc_field = NULL;
340 priv->bcc_field = NULL;
341 priv->subject_field = NULL;
342 priv->attachments = NULL;
344 priv->zoom_level = 1.0;
346 priv->cc_caption = NULL;
347 priv->bcc_caption = NULL;
348 priv->update_caption_visibility = FALSE;
350 priv->priority_flags = 0;
352 priv->find_toolbar = NULL;
353 priv->last_search = NULL;
355 priv->draft_msg = NULL;
356 priv->outbox_msg = NULL;
357 priv->clipboard_change_handler_id = 0;
362 /* FIXME: this is a dup from the one in gtk/ */
365 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
367 static ModestPairList*
368 get_transports (void)
370 GSList *transports = NULL;
372 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
373 GSList *accounts = modest_account_mgr_account_names (account_mgr,
374 TRUE /* only enabled accounts. */);
376 GSList *cursor = accounts;
378 gchar *account_name = cursor->data;
379 gchar *from_string = NULL;
381 from_string = modest_account_mgr_get_from_string (account_mgr,
385 if (from_string && account_name) {
386 gchar *name = account_name;
387 ModestPair *pair = modest_pair_new ((gpointer) name,
388 (gpointer) from_string , TRUE);
389 transports = g_slist_prepend (transports, pair);
392 cursor = cursor->next;
394 g_slist_free (accounts); /* only free the accounts, not the elements,
395 * because they are used in the pairlist */
401 init_window (ModestMsgEditWindow *obj)
403 GtkWidget *from_caption, *to_caption, *subject_caption;
404 GtkWidget *main_vbox;
405 ModestMsgEditWindowPrivate *priv;
407 GtkSizeGroup *size_group;
409 GtkWidget *subject_box;
410 GtkWidget *attachment_icon;
411 GtkWidget *window_box;
412 #if (GTK_MINOR_VERSION >= 10)
413 GdkAtom deserialize_type;
415 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
417 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
419 /* Note: This ModestPairList* must exist for as long as the combo
420 * that uses it, because the ModestComboBox uses the ID opaquely,
421 * so it can't know how to manage its memory. */
422 priv->from_field_protos = get_transports ();
424 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
426 priv->to_field = modest_recpt_editor_new ();
427 priv->cc_field = modest_recpt_editor_new ();
428 priv->bcc_field = modest_recpt_editor_new ();
429 subject_box = gtk_hbox_new (FALSE, 0);
430 priv->priority_icon = gtk_image_new ();
431 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
432 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
433 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
434 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
435 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
436 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
437 priv->add_attachment_button = gtk_button_new ();
438 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
439 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
440 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
441 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
442 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
443 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
444 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
445 priv->attachments_view = modest_attachments_view_new (NULL);
447 priv->header_box = gtk_vbox_new (FALSE, 0);
449 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
450 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
451 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
452 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
453 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
454 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
455 g_object_unref (size_group);
457 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
458 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
459 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
460 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
461 gtk_size_group_add_widget (size_group, priv->subject_field);
462 gtk_size_group_add_widget (size_group, priv->attachments_view);
463 g_object_unref (size_group);
465 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
466 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
467 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
468 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
469 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
470 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
471 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
474 priv->msg_body = wp_text_view_new ();
475 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
476 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
477 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
478 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
479 #if (GTK_MINOR_VERSION >= 10)
480 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
481 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
483 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
484 deserialize_type, TRUE);
486 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
488 priv->find_toolbar = hildon_find_toolbar_new (NULL);
489 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
491 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
493 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
494 G_CALLBACK (text_buffer_refresh_attributes), obj);
495 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
496 G_CALLBACK (text_buffer_can_undo), obj);
497 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
498 G_CALLBACK (text_buffer_can_redo), obj);
499 g_signal_connect (G_OBJECT (obj), "window-state-event",
500 G_CALLBACK (modest_msg_edit_window_window_state_event),
502 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
503 G_CALLBACK (text_buffer_apply_tag), obj);
504 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
505 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
506 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
507 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
508 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
509 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
511 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
512 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
514 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
515 G_CALLBACK (msg_body_focus), obj);
516 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
517 G_CALLBACK (msg_body_focus), obj);
518 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
519 "changed", G_CALLBACK (recpt_field_changed), obj);
520 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
521 "changed", G_CALLBACK (recpt_field_changed), obj);
522 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
523 "changed", G_CALLBACK (recpt_field_changed), obj);
524 recpt_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
525 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
527 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
528 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
530 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
531 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
532 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
533 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
535 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
537 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
538 frame = gtk_frame_new (NULL);
539 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
541 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
542 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
543 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
545 window_box = gtk_vbox_new (FALSE, 0);
546 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
547 gtk_container_add (GTK_CONTAINER(obj), window_box);
548 priv->scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
549 gtk_container_add (GTK_CONTAINER (frame), priv->scroll_area);
551 gtk_container_set_focus_vadjustment (GTK_CONTAINER (priv->scroll_area),
552 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
554 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
555 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
560 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
562 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
564 if (g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
565 priv->clipboard_change_handler_id))
566 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
567 priv->clipboard_change_handler_id);
571 modest_msg_edit_window_finalize (GObject *obj)
573 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
575 /* Sanity check: shouldn't be needed, the window mgr should
576 call this function before */
577 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
579 if (priv->draft_msg != NULL) {
580 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
581 if (TNY_IS_HEADER (header)) {
582 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
583 modest_window_mgr_unregister_header (mgr, header);
585 g_object_unref (priv->draft_msg);
586 priv->draft_msg = NULL;
588 if (priv->outbox_msg != NULL) {
589 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
590 if (TNY_IS_HEADER (header)) {
591 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
592 modest_window_mgr_unregister_header (mgr, header);
594 g_object_unref (priv->outbox_msg);
595 priv->outbox_msg = NULL;
598 /* This had to stay alive for as long as the combobox that used it: */
599 modest_pair_list_free (priv->from_field_protos);
601 G_OBJECT_CLASS(parent_class)->finalize (obj);
605 menubar_to_menu (GtkUIManager *ui_manager)
607 GtkWidget *main_menu;
611 /* Create new main menu */
612 main_menu = gtk_menu_new();
614 /* Get the menubar from the UI manager */
615 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
617 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
621 menu = GTK_WIDGET (iter->data);
622 gtk_widget_reparent(menu, main_menu);
624 iter = g_list_next (iter);
630 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type)
632 GdkPixbufLoader *loader;
635 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
640 tny_stream_reset (TNY_STREAM (stream));
641 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
642 unsigned char read_buffer[128];
644 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
645 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
649 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
650 g_object_ref (pixbuf);
651 gdk_pixbuf_loader_close (loader, NULL);
652 g_object_unref (loader);
654 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
655 GdkPixbuf *new_pixbuf;
657 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
658 gdk_pixbuf_get_width (pixbuf);
659 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
660 g_object_unref (pixbuf);
668 replace_with_attachments (ModestMsgEditWindow *self, GList *attachments)
670 ModestMsgEditWindowPrivate *priv;
673 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
675 for (node = attachments; node != NULL; node = g_list_next (node)) {
676 TnyMimePart *part = (TnyMimePart *) node->data;
677 const gchar *cid = tny_mime_part_get_content_id (part);
678 const gchar *mime_type = tny_mime_part_get_content_type (part);
679 if ((cid != NULL)&&(mime_type != NULL)) {
680 TnyStream *stream = tny_mime_part_get_stream (part);
681 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type);
682 g_object_unref (stream);
684 if (pixbuf != NULL) {
685 /* wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf); */
686 g_object_unref (pixbuf);
693 update_last_cid (ModestMsgEditWindow *self, GList *attachments)
696 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
698 for (node = attachments; node != NULL; node = g_list_next (node)) {
699 TnyMimePart *part = (TnyMimePart *) node->data;
700 const gchar *cid = tny_mime_part_get_content_id (part);
702 char *invalid = NULL;
703 gint int_cid = strtol (cid, &invalid, 10);
704 if ((invalid != NULL) && (*invalid == '\0') && (int_cid > priv->last_cid)) {
705 priv->last_cid = int_cid;
713 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
716 const gchar *to, *cc, *bcc, *subject;
718 ModestMsgEditWindowPrivate *priv;
720 TnyHeaderFlags priority_flags;
721 TnyFolder *msg_folder;
722 gboolean is_html = FALSE;
724 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
725 g_return_if_fail (TNY_IS_MSG (msg));
727 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
729 header = tny_msg_get_header (msg);
730 to = tny_header_get_to (header);
731 cc = tny_header_get_cc (header);
732 bcc = tny_header_get_bcc (header);
733 subject = tny_header_get_subject (header);
734 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
737 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
739 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
740 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
741 gtk_widget_show (priv->cc_caption);
742 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
743 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
744 gtk_widget_hide (priv->cc_caption);
747 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
748 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
749 gtk_widget_show (priv->bcc_caption);
750 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
751 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
752 gtk_widget_hide (priv->bcc_caption);
755 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
756 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
759 update_window_title (self);
761 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
762 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
764 if ((body == NULL)||(body[0] == '\0')) {
766 body = modest_text_utils_convert_to_html ("");
769 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
770 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
773 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
776 if (preserve_is_rich && !is_html) {
777 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
778 /* Get the default format required from configuration */
779 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
780 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
783 /* Set the default focus depending on having already a To: field or not */
784 if ((!to)||(*to == '\0')) {
785 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
787 gtk_widget_grab_focus (priv->msg_body);
790 /* TODO: lower priority, select in the From: combo to the
791 value that comes from msg <- not sure, should it be
794 /* Add attachments to the view */
795 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
796 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
797 if (priv->attachments == NULL) {
798 gtk_widget_hide (priv->attachments_caption);
800 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
801 gtk_widget_show_all (priv->attachments_caption);
802 replace_with_attachments (self, priv->attachments);
804 update_last_cid (self, priv->attachments);
806 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
808 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
809 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
811 reset_modified (self);
813 update_dimmed (self);
814 text_buffer_can_undo (priv->text_buffer, FALSE, self);
815 text_buffer_can_redo (priv->text_buffer, FALSE, self);
817 /* we should set a reference to the incoming message if it is a draft */
818 msg_folder = tny_msg_get_folder (msg);
820 if (modest_tny_folder_is_local_folder (msg_folder)) {
821 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
822 if (type == TNY_FOLDER_TYPE_DRAFTS)
823 priv->draft_msg = g_object_ref(msg);
824 if (type == TNY_FOLDER_TYPE_OUTBOX)
825 priv->outbox_msg = g_object_ref(msg);
827 g_object_unref (msg_folder);
832 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
835 GList *item_children, *node;
836 GtkWidget *bin_child;
838 bin_child = gtk_bin_get_child (GTK_BIN(item));
840 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
842 for (node = item_children; node != NULL; node = g_list_next (node)) {
843 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
844 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
847 g_list_free (item_children);
851 menu_tool_button_dont_expand (GtkMenuToolButton *item)
854 GList *item_children, *node;
856 box = gtk_bin_get_child (GTK_BIN (item));
857 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
858 item_children = gtk_container_get_children (GTK_CONTAINER (box));
860 for (node = item_children; node != NULL; node = g_list_next (node)) {
861 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
862 if (GTK_IS_TOGGLE_BUTTON (node->data))
863 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
864 else if (GTK_IS_BUTTON (node->data))
865 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
867 g_list_free (item_children);
872 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
874 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
875 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
876 GtkWidget *placeholder;
877 GtkWidget *tool_item;
882 GtkWidget *sizes_menu;
883 GtkWidget *fonts_menu;
884 GSList *radio_group = NULL;
889 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
890 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
892 /* should we hide the toolbar? */
893 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
894 gtk_widget_hide (parent_priv->toolbar);
896 /* Font color placeholder */
897 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
898 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
901 tool_item = GTK_WIDGET (gtk_tool_item_new ());
902 priv->font_color_button = hildon_color_button_new ();
903 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
904 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
905 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
906 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
907 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
908 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
909 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
911 /* Font size and face placeholder */
912 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
913 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
915 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
916 priv->size_tool_button_label = gtk_label_new (NULL);
917 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
918 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
919 size_text,"</span>", NULL);
920 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
922 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
923 sizes_menu = gtk_menu_new ();
924 priv->size_items_group = NULL;
926 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
927 GtkWidget *size_menu_item;
929 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
930 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
931 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
932 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
933 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
934 gtk_widget_show (size_menu_item);
936 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
940 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
941 GtkWidget *item = (GtkWidget *) node->data;
942 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
946 priv->size_items_group = g_slist_reverse (priv->size_items_group);
947 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
948 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
949 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
950 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
951 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
952 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
953 priv->font_size_toolitem = tool_item;
956 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
957 priv->font_tool_button_label = gtk_label_new (NULL);
958 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
959 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
961 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
962 fonts_menu = gtk_menu_new ();
963 priv->font_items_group = NULL;
965 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
966 GtkWidget *font_menu_item;
967 GtkWidget *child_label;
969 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
970 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
971 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
972 wp_get_font_name (font_index), "</span>", NULL);
973 gtk_label_set_markup (GTK_LABEL (child_label), markup);
976 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
977 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
978 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
979 gtk_widget_show (font_menu_item);
981 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
984 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
985 GtkWidget *item = (GtkWidget *) node->data;
986 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
989 priv->font_items_group = g_slist_reverse (priv->font_items_group);
990 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
991 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
992 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
993 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
994 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
995 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
996 priv->font_face_toolitem = tool_item;
998 /* Set expand and homogeneous for remaining items */
999 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1000 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1001 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1002 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1003 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1004 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1005 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1006 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1007 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1015 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1018 ModestWindowPrivate *parent_priv;
1019 ModestMsgEditWindowPrivate *priv;
1020 GtkActionGroup *action_group;
1021 GError *error = NULL;
1022 GdkPixbuf *window_icon = NULL;
1025 gboolean prefer_formatted;
1027 ModestPair *account_pair = NULL;
1029 g_return_val_if_fail (msg, NULL);
1030 g_return_val_if_fail (account_name, NULL);
1032 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
1034 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1035 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1037 parent_priv->ui_manager = gtk_ui_manager_new();
1038 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
1039 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1041 /* Add common actions */
1042 gtk_action_group_add_actions (action_group,
1043 modest_msg_edit_action_entries,
1044 G_N_ELEMENTS (modest_msg_edit_action_entries),
1046 gtk_action_group_add_toggle_actions (action_group,
1047 modest_msg_edit_toggle_action_entries,
1048 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
1050 gtk_action_group_add_radio_actions (action_group,
1051 modest_msg_edit_alignment_radio_action_entries,
1052 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
1054 G_CALLBACK (modest_ui_actions_on_change_justify),
1056 gtk_action_group_add_radio_actions (action_group,
1057 modest_msg_edit_zoom_action_entries,
1058 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
1060 G_CALLBACK (modest_ui_actions_on_change_zoom),
1062 gtk_action_group_add_radio_actions (action_group,
1063 modest_msg_edit_priority_action_entries,
1064 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
1066 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
1068 gtk_action_group_add_radio_actions (action_group,
1069 modest_msg_edit_file_format_action_entries,
1070 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
1071 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
1072 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
1074 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1075 g_object_unref (action_group);
1077 /* Load the UI definition */
1078 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
1080 if (error != NULL) {
1081 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
1082 g_clear_error (&error);
1085 /* Add accelerators */
1086 gtk_window_add_accel_group (GTK_WINDOW (obj),
1087 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1090 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
1091 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1094 init_window (MODEST_MSG_EDIT_WINDOW(obj));
1096 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1098 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1100 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1101 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1103 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
1105 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
1106 if (account_pair != NULL)
1107 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
1109 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1111 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1113 /* Set window icon */
1114 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
1116 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1117 g_object_unref (window_icon);
1120 /* Dim at start clipboard actions */
1121 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
1122 gtk_action_set_sensitive (action, FALSE);
1123 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
1124 gtk_action_set_sensitive (action, FALSE);
1125 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
1126 gtk_action_set_sensitive (action, FALSE);
1128 /* Update select all */
1129 update_select_all_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1130 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu");
1131 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (edit_menu_activated), obj);
1132 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu");
1133 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (view_menu_activated), obj);
1135 /* set initial state of cc and bcc */
1136 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
1137 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1138 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
1139 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
1140 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1141 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
1143 /* Setup the file format */
1144 conf = modest_runtime_get_conf ();
1145 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
1147 g_clear_error (&error);
1148 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
1150 file_format = (prefer_formatted) ?
1151 MODEST_FILE_FORMAT_FORMATTED_TEXT :
1152 MODEST_FILE_FORMAT_PLAIN_TEXT;
1153 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
1155 update_paste_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1156 priv->update_caption_visibility = TRUE;
1158 reset_modified (MODEST_MSG_EDIT_WINDOW (obj));
1160 return (ModestWindow*) obj;
1164 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1166 GString **string_buffer = (GString **) user_data;
1168 *string_buffer = g_string_append (*string_buffer, buffer);
1174 * @result: A new string which should be freed with g_free().
1177 get_formatted_data (ModestMsgEditWindow *edit_window)
1179 ModestMsgEditWindowPrivate *priv;
1180 GString *string_buffer = g_string_new ("");
1182 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1184 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1186 return g_string_free (string_buffer, FALSE);
1191 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1194 const gchar *account_name;
1195 ModestMsgEditWindowPrivate *priv;
1197 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1199 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1201 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1202 g_return_val_if_fail (account_name, NULL);
1205 /* don't free these (except from) */
1206 data = g_slice_new0 (MsgData);
1207 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1209 data->account_name = g_strdup (account_name);
1210 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1211 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1212 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1213 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1214 if (priv->draft_msg) {
1215 data->draft_msg = g_object_ref (priv->draft_msg);
1217 if (priv->outbox_msg) {
1218 data->draft_msg = g_object_ref (priv->outbox_msg);
1220 data->draft_msg = NULL;
1223 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1225 gtk_text_buffer_get_bounds (buf, &b, &e);
1226 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1228 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1229 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1231 data->html_body = NULL;
1233 /* deep-copy the data */
1234 GList *cursor = priv->attachments;
1235 data->attachments = NULL;
1237 if (!(TNY_IS_MIME_PART(cursor->data))) {
1238 g_warning ("strange data in attachment list");
1239 cursor = g_list_next (cursor);
1242 data->attachments = g_list_append (data->attachments,
1243 g_object_ref (cursor->data));
1244 cursor = g_list_next (cursor);
1247 data->priority_flags = priv->priority_flags;
1254 unref_gobject (GObject *obj, gpointer data)
1256 if (!G_IS_OBJECT(obj))
1258 g_object_unref (obj);
1262 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1265 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1273 g_free (data->subject);
1274 g_free (data->plain_body);
1275 g_free (data->html_body);
1276 g_free (data->account_name);
1278 if (data->draft_msg != NULL) {
1279 g_object_unref (data->draft_msg);
1280 data->draft_msg = NULL;
1283 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1284 g_list_free (data->attachments);
1286 g_slice_free (MsgData, data);
1290 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1293 ModestMsgEditWindowPrivate *priv = NULL;
1294 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1296 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1298 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1300 return MODEST_MSG_EDIT_FORMAT_HTML;
1302 return MODEST_MSG_EDIT_FORMAT_TEXT;
1306 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1307 ModestMsgEditFormat format)
1309 ModestMsgEditWindowPrivate *priv;
1311 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1312 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1315 case MODEST_MSG_EDIT_FORMAT_HTML:
1316 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1318 case MODEST_MSG_EDIT_FORMAT_TEXT:
1319 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1322 g_return_if_reached ();
1326 ModestMsgEditFormatState *
1327 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1329 ModestMsgEditFormatState *format_state = NULL;
1330 ModestMsgEditWindowPrivate *priv;
1331 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1333 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1334 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1336 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1338 format_state = g_new0 (ModestMsgEditFormatState, 1);
1339 format_state->bold = buffer_format->bold&0x1;
1340 format_state->italics = buffer_format->italic&0x1;
1341 format_state->bullet = buffer_format->bullet&0x1;
1342 format_state->color = buffer_format->color;
1343 format_state->font_size = buffer_format->font_size;
1344 format_state->font_family = wp_get_font_name (buffer_format->font);
1345 format_state->justification = buffer_format->justification;
1346 g_free (buffer_format);
1348 return format_state;
1353 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1354 const ModestMsgEditFormatState *format_state)
1356 ModestMsgEditWindowPrivate *priv;
1357 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1358 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1359 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1360 g_return_if_fail (format_state != NULL);
1362 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1363 gtk_widget_grab_focus (priv->msg_body);
1364 buffer_format->bold = (format_state->bold != FALSE);
1365 buffer_format->italic = (format_state->italics != FALSE);
1366 buffer_format->color = format_state->color;
1367 buffer_format->font_size = format_state->font_size;
1368 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1369 buffer_format->justification = format_state->justification;
1370 buffer_format->bullet = format_state->bullet;
1372 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1374 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1375 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1376 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1377 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1378 buffer_format->cs.font = (buffer_format->font != current_format->font);
1379 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1380 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1382 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1383 if (buffer_format->cs.bold) {
1384 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1386 if (buffer_format->cs.italic) {
1387 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1389 if (buffer_format->cs.color) {
1390 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1392 if (buffer_format->cs.font_size) {
1393 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1395 if (buffer_format->cs.justification) {
1396 switch (buffer_format->justification) {
1397 case GTK_JUSTIFY_LEFT:
1398 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1400 case GTK_JUSTIFY_CENTER:
1401 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1403 case GTK_JUSTIFY_RIGHT:
1404 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1411 if (buffer_format->cs.font) {
1412 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1414 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1415 if (buffer_format->cs.bullet) {
1416 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((buffer_format->bullet)?1:0));
1418 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1420 g_free (current_format);
1425 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1427 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1429 ModestWindowPrivate *parent_priv;
1430 ModestMsgEditWindowPrivate *priv;
1431 GtkWidget *new_size_menuitem;
1432 GtkWidget *new_font_menuitem;
1434 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1435 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1437 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1438 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1439 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1440 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1442 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1443 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1444 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1447 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1449 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1450 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1452 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1453 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1455 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1456 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1458 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1459 G_CALLBACK (modest_msg_edit_window_color_button_change),
1461 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1462 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1463 G_CALLBACK (modest_msg_edit_window_color_button_change),
1466 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1467 buffer_format->font_size))->data);
1468 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1472 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1473 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1474 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1476 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1477 G_CALLBACK (modest_msg_edit_window_size_change),
1479 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1480 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1481 G_CALLBACK (modest_msg_edit_window_size_change),
1485 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1486 buffer_format->font))->data);
1487 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1491 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1492 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1493 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1495 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1496 G_CALLBACK (modest_msg_edit_window_font_change),
1498 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1499 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1500 G_CALLBACK (modest_msg_edit_window_font_change),
1504 g_free (buffer_format);
1510 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1513 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1514 ModestMsgEditWindowPrivate *priv;
1515 GtkWidget *dialog = NULL;
1517 const GdkColor *new_color = NULL;
1519 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1520 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1522 #ifdef MODEST_HILDON_VERSION_0
1523 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1524 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1526 dialog = hildon_color_chooser_new ();
1527 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1528 #endif /*MODEST_HILDON_VERSION_0*/
1529 g_free (buffer_format);
1531 response = gtk_dialog_run (GTK_DIALOG (dialog));
1533 case GTK_RESPONSE_OK: {
1534 #ifdef MODEST_HILDON_VERSION_0
1535 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1538 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1540 #endif /*MODEST_HILDON_VERSION_0*/
1547 gtk_widget_destroy (dialog);
1549 if (new_color != NULL)
1550 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1555 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1558 ModestMsgEditWindowPrivate *priv;
1559 GtkWidget *dialog = NULL;
1561 GdkColor *old_color = NULL;
1562 const GdkColor *new_color = NULL;
1564 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1565 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1567 #ifdef MODEST_HILDON_VERSION_0
1568 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1569 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1571 dialog = hildon_color_chooser_new ();
1572 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1573 #endif /*MODEST_HILDON_VERSION_9*/
1575 response = gtk_dialog_run (GTK_DIALOG (dialog));
1577 case GTK_RESPONSE_OK: {
1578 #ifdef MODEST_HILDON_VERSION_0
1579 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1582 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1584 #endif /*MODEST_HILDON_VERSION_0*/
1590 gtk_widget_destroy (dialog);
1592 if (new_color != NULL)
1593 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1597 static TnyStream* create_stream_for_uri (const gchar* uri)
1602 TnyStream *result = NULL;
1604 GnomeVFSHandle *handle = NULL;
1605 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1606 if (test == GNOME_VFS_OK) {
1607 /* Create the tinymail stream: */
1608 /* Presumably tinymai will call gnome_vfs_close (handle) later. */
1609 result = TNY_STREAM (tny_vfs_stream_new (handle));
1616 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1619 ModestMsgEditWindowPrivate *priv;
1620 GtkWidget *dialog = NULL;
1622 GSList *uris = NULL;
1623 GSList *uri_node = NULL;
1625 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1627 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1628 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1629 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1631 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1633 response = gtk_dialog_run (GTK_DIALOG (dialog));
1635 case GTK_RESPONSE_OK:
1636 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1641 gtk_widget_destroy (dialog);
1643 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1645 GnomeVFSHandle *handle = NULL;
1646 GnomeVFSResult result;
1647 GtkTextIter position;
1648 GtkTextMark *insert_mark;
1650 uri = (const gchar *) uri_node->data;
1651 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1652 if (result == GNOME_VFS_OK) {
1654 GnomeVFSFileInfo info;
1655 gchar *filename, *basename, *escaped_filename;
1656 TnyMimePart *mime_part;
1658 const gchar *mime_type = NULL;
1659 GnomeVFSURI *vfs_uri;
1661 vfs_uri = gnome_vfs_uri_new (uri);
1663 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1664 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1665 g_free (escaped_filename);
1666 gnome_vfs_uri_unref (vfs_uri);
1668 if (gnome_vfs_get_file_info (uri, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
1669 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1671 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1673 mime_part = tny_platform_factory_new_mime_part
1674 (modest_runtime_get_platform_factory ());
1676 TnyStream *stream = create_stream_for_uri (uri);
1677 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1679 content_id = g_strdup_printf ("%d", priv->last_cid);
1680 tny_mime_part_set_content_id (mime_part, content_id);
1681 g_free (content_id);
1684 basename = g_path_get_basename (filename);
1685 tny_mime_part_set_filename (mime_part, basename);
1688 pixbuf = pixbuf_from_stream (stream, mime_type);
1690 if (pixbuf != NULL) {
1691 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1692 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1693 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1696 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1697 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1699 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1700 gtk_widget_show_all (priv->attachments_caption);
1701 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1711 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
1714 ModestMsgEditWindowPrivate *priv;
1715 GtkWidget *dialog = NULL;
1717 GSList *uris = NULL;
1720 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1722 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1723 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
1724 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1726 response = gtk_dialog_run (GTK_DIALOG (dialog));
1728 case GTK_RESPONSE_OK:
1729 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1734 gtk_widget_destroy (dialog);
1736 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1737 const gchar *uri = (const gchar *) uri_node->data;
1738 modest_msg_edit_window_attach_file_one (window, uri);
1740 g_slist_foreach (uris, (GFunc) g_free, NULL);
1741 g_slist_free (uris);
1745 modest_msg_edit_window_attach_file_one (
1746 ModestMsgEditWindow *window,
1749 g_return_if_fail (window);
1750 g_return_if_fail (uri);
1752 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1755 GnomeVFSHandle *handle = NULL;
1756 GnomeVFSResult result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1757 if (result == GNOME_VFS_OK) {
1758 TnyMimePart *mime_part;
1760 const gchar *mime_type = NULL;
1762 gchar *escaped_filename;
1765 GnomeVFSFileInfo info;
1766 GnomeVFSURI *vfs_uri;
1768 vfs_uri = gnome_vfs_uri_new (uri);
1771 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1772 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1773 g_free (escaped_filename);
1774 gnome_vfs_uri_unref (vfs_uri);
1776 if (gnome_vfs_get_file_info (uri,
1778 GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
1779 GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1781 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1782 mime_part = tny_platform_factory_new_mime_part
1783 (modest_runtime_get_platform_factory ());
1784 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1786 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1788 content_id = g_strdup_printf ("%d", priv->last_cid);
1789 tny_mime_part_set_content_id (mime_part, content_id);
1790 g_free (content_id);
1793 basename = g_path_get_basename (filename);
1794 tny_mime_part_set_filename (mime_part, basename);
1797 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1798 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1800 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1801 gtk_widget_show_all (priv->attachments_caption);
1802 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1808 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1811 ModestMsgEditWindowPrivate *priv;
1812 gboolean clean_list = FALSE;
1814 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1815 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1817 if (att_list == NULL) {
1818 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1822 if (att_list == NULL) {
1823 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1825 GtkWidget *confirmation_dialog = NULL;
1826 gboolean dialog_response;
1828 gchar *message = NULL;
1829 const gchar *filename = NULL;
1831 if (att_list->next == NULL) {
1832 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1836 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1837 att_list->next == NULL), filename);
1838 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1840 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1841 gtk_widget_destroy (confirmation_dialog);
1842 if (!dialog_response) {
1844 g_list_free (att_list);
1847 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1849 for (node = att_list; node != NULL; node = g_list_next (node)) {
1850 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1851 const gchar *att_id;
1852 priv->attachments = g_list_remove (priv->attachments, mime_part);
1854 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1856 if (priv->attachments == NULL)
1857 gtk_widget_hide (priv->attachments_caption);
1858 att_id = tny_mime_part_get_content_id (mime_part);
1860 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1862 g_object_unref (mime_part);
1863 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1868 g_list_free (att_list);
1872 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1875 ModestMsgEditWindowPrivate *priv;
1876 GdkColor *new_color;
1877 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1879 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1880 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1883 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1885 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1887 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1889 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1894 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1897 ModestMsgEditWindowPrivate *priv;
1898 gint new_size_index;
1899 ModestMsgEditWindow *window;
1902 window = MODEST_MSG_EDIT_WINDOW (userdata);
1903 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1904 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1906 if (gtk_check_menu_item_get_active (menu_item)) {
1908 WPTextBufferFormat format;
1910 memset (&format, 0, sizeof (format));
1911 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1913 label = gtk_bin_get_child (GTK_BIN (menu_item));
1915 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1916 format.cs.font_size = TRUE;
1917 format.cs.text_position = TRUE;
1918 format.cs.font = TRUE;
1919 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1920 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1922 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1923 (gpointer) wp_get_font_size_index (new_size_index, 12)))
1924 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1926 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1927 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1928 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1934 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1937 ModestMsgEditWindowPrivate *priv;
1938 gint new_font_index;
1939 ModestMsgEditWindow *window;
1942 window = MODEST_MSG_EDIT_WINDOW (userdata);
1943 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1944 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1946 if (gtk_check_menu_item_get_active (menu_item)) {
1949 label = gtk_bin_get_child (GTK_BIN (menu_item));
1951 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1953 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1954 (gpointer) new_font_index))
1955 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1957 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1958 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1959 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1965 modest_msg_edit_window_set_zoom (ModestWindow *window,
1968 ModestMsgEditWindowPrivate *priv;
1969 ModestWindowPrivate *parent_priv;
1970 GtkRadioAction *zoom_radio_action;
1972 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1974 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1975 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1976 priv->zoom_level = zoom;
1977 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom*DEFAULT_FONT_SCALE);
1979 /* Zoom level menu options should be updated with the current zoom level */
1980 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1981 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1982 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1983 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1984 /* FIXME: Not availible before Gtk 2.10 */
1986 gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
1991 modest_msg_edit_window_get_zoom (ModestWindow *window)
1993 ModestMsgEditWindowPrivate *priv;
1995 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1997 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1998 return priv->zoom_level;
2002 zoom_allowed (ModestMsgEditWindow *window)
2006 focus = gtk_window_get_focus (GTK_WINDOW (window));
2007 return (focus != NULL && WP_IS_TEXT_VIEW (focus));
2011 modest_msg_edit_window_zoom_plus (ModestWindow *window)
2013 ModestWindowPrivate *parent_priv;
2014 GtkRadioAction *zoom_radio_action;
2015 GSList *group, *node;
2017 /* First we check if the text view is focused. If not, zooming is not allowed */
2018 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2019 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2023 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2024 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2025 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2027 group = gtk_radio_action_get_group (zoom_radio_action);
2029 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
2030 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
2034 for (node = group; node != NULL; node = g_slist_next (node)) {
2035 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
2036 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
2044 modest_msg_edit_window_zoom_minus (ModestWindow *window)
2046 ModestWindowPrivate *parent_priv;
2047 GtkRadioAction *zoom_radio_action;
2048 GSList *group, *node;
2050 /* First we check if the text view is focused. If not, zooming is not allowed */
2051 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2052 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2056 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2057 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2058 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2060 group = gtk_radio_action_get_group (zoom_radio_action);
2062 for (node = group; node != NULL; node = g_slist_next (node)) {
2063 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
2064 if (node->next != NULL) {
2065 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
2068 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
2076 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2078 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2079 ModestWindowPrivate *parent_priv;
2080 ModestWindowMgr *mgr;
2081 gboolean is_fullscreen;
2082 GtkAction *fs_toggle_action;
2085 mgr = modest_runtime_get_window_mgr ();
2086 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2088 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2090 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2091 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2092 if (is_fullscreen != active)
2093 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2101 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
2103 ModestWindowPrivate *parent_priv;
2104 GtkAction *fs_toggle_action;
2107 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2109 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2110 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
2111 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
2115 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2118 ModestMsgEditWindowPrivate *priv = NULL;
2119 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2121 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2122 if (!priv->update_caption_visibility)
2125 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2127 gtk_widget_show (priv->cc_caption);
2129 gtk_widget_hide (priv->cc_caption);
2131 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2135 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2138 ModestMsgEditWindowPrivate *priv = NULL;
2139 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2141 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2142 if (!priv->update_caption_visibility)
2145 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2147 gtk_widget_show (priv->bcc_caption);
2149 gtk_widget_hide (priv->bcc_caption);
2151 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2155 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2156 ModestRecptEditor *editor)
2158 ModestMsgEditWindowPrivate *priv;
2160 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2161 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2162 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2164 if (editor == NULL) {
2165 GtkWidget *view_focus;
2166 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2168 /* This code should be kept in sync with ModestRecptEditor. The
2169 textview inside the recpt editor is the one that really gets the
2170 focus. As it's inside a scrolled window, and this one inside the
2171 hbox recpt editor inherits from, we'll need to go up in the
2172 hierarchy to know if the text view is part of the recpt editor
2173 or if it's a different text entry */
2175 if (gtk_widget_get_parent (view_focus)) {
2176 GtkWidget *first_parent;
2178 first_parent = gtk_widget_get_parent (view_focus);
2179 if (gtk_widget_get_parent (first_parent) &&
2180 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2181 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2186 editor = MODEST_RECPT_EDITOR (priv->to_field);
2190 modest_address_book_select_addresses (editor);
2195 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2197 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2199 modest_msg_edit_window_open_addressbook (window, NULL);
2203 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2204 gboolean show_toolbar)
2206 ModestWindowPrivate *parent_priv;
2208 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2209 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2211 /* FIXME: we can not just use the code of
2212 modest_msg_edit_window_setup_toolbar because it has a
2213 mixture of both initialization and creation code. */
2216 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2218 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2222 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2223 TnyHeaderFlags priority_flags)
2225 ModestMsgEditWindowPrivate *priv;
2226 ModestWindowPrivate *parent_priv;
2228 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2230 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2231 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2232 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2234 if (priv->priority_flags != priority_flags) {
2235 GtkAction *priority_action = NULL;
2237 priv->priority_flags = priority_flags;
2239 switch (priority_flags) {
2240 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2241 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2242 gtk_widget_show (priv->priority_icon);
2243 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2244 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2246 case TNY_HEADER_FLAG_LOW_PRIORITY:
2247 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2248 gtk_widget_show (priv->priority_icon);
2249 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2250 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2253 gtk_widget_hide (priv->priority_icon);
2254 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2255 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2258 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2259 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2264 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2267 ModestMsgEditWindowPrivate *priv;
2268 ModestWindowPrivate *parent_priv;
2269 gint current_format;
2271 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2273 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2274 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2276 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2277 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2279 if (current_format != file_format) {
2280 switch (file_format) {
2281 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2282 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2284 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2288 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2289 response = gtk_dialog_run (GTK_DIALOG (dialog));
2290 gtk_widget_destroy (dialog);
2291 if (response == GTK_RESPONSE_OK) {
2292 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2294 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2295 modest_maemo_toggle_action_set_active_block_notify (action, TRUE);
2300 update_dimmed (window);
2305 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2308 ModestMsgEditWindowPrivate *priv;
2309 WPTextBufferFormat oldfmt, fmt;
2310 gint old_position = 0;
2314 GdkColor *color = NULL;
2315 gboolean bold, bold_set, italic, italic_set;
2316 gboolean underline, underline_set;
2317 gboolean strikethrough, strikethrough_set;
2318 gboolean position_set;
2319 gboolean font_size_set, font_set, color_set;
2322 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2323 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2325 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2327 /* First we get the currently selected font information */
2328 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2329 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2331 switch (oldfmt.text_position) {
2332 case TEXT_POSITION_NORMAL:
2335 case TEXT_POSITION_SUPERSCRIPT:
2343 g_object_set (G_OBJECT (dialog),
2344 "bold", oldfmt.bold != FALSE,
2345 "bold-set", !oldfmt.cs.bold,
2346 "underline", oldfmt.underline != FALSE,
2347 "underline-set", !oldfmt.cs.underline,
2348 "italic", oldfmt.italic != FALSE,
2349 "italic-set", !oldfmt.cs.italic,
2350 "strikethrough", oldfmt.strikethrough != FALSE,
2351 "strikethrough-set", !oldfmt.cs.strikethrough,
2352 "color", &oldfmt.color,
2353 "color-set", !oldfmt.cs.color,
2354 "size", wp_font_size[oldfmt.font_size],
2355 "size-set", !oldfmt.cs.font_size,
2356 "position", old_position,
2357 "position-set", !oldfmt.cs.text_position,
2358 "family", wp_get_font_name (oldfmt.font),
2359 "family-set", !oldfmt.cs.font,
2362 gtk_widget_show_all (dialog);
2363 response = gtk_dialog_run (GTK_DIALOG (dialog));
2364 if (response == GTK_RESPONSE_OK) {
2366 g_object_get( dialog,
2368 "bold-set", &bold_set,
2369 "underline", &underline,
2370 "underline-set", &underline_set,
2372 "italic-set", &italic_set,
2373 "strikethrough", &strikethrough,
2374 "strikethrough-set", &strikethrough_set,
2376 "color-set", &color_set,
2378 "size-set", &font_size_set,
2379 "family", &font_name,
2380 "family-set", &font_set,
2381 "position", &position,
2382 "position-set", &position_set,
2387 if (response == GTK_RESPONSE_OK) {
2388 memset(&fmt, 0, sizeof(fmt));
2394 fmt.italic = italic;
2395 fmt.cs.italic = TRUE;
2397 if (underline_set) {
2398 fmt.underline = underline;
2399 fmt.cs.underline = TRUE;
2401 if (strikethrough_set) {
2402 fmt.strikethrough = strikethrough;
2403 fmt.cs.strikethrough = TRUE;
2408 ? TEXT_POSITION_NORMAL
2409 : ( ( position == 1 )
2410 ? TEXT_POSITION_SUPERSCRIPT
2411 : TEXT_POSITION_SUBSCRIPT );
2412 fmt.cs.text_position = TRUE;
2416 fmt.cs.color = TRUE;
2419 fmt.font = wp_get_font_index(font_name,
2424 if (font_size_set) {
2425 fmt.font_size = wp_get_font_size_index(
2426 font_size, DEFAULT_FONT_SIZE);
2427 fmt.cs.font_size = TRUE;
2429 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2431 gtk_widget_destroy (dialog);
2433 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2437 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2439 ModestMsgEditWindowPrivate *priv;
2441 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2442 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2444 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2446 update_dimmed (window);
2451 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2453 ModestMsgEditWindowPrivate *priv;
2455 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2456 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2458 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2460 update_dimmed (window);
2465 update_dimmed (ModestMsgEditWindow *window)
2467 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2468 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2472 gboolean editor_focused;
2474 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2475 editor_focused = gtk_widget_is_focus (priv->msg_body);
2477 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2478 gtk_action_set_sensitive (action, rich_text && editor_focused);
2479 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2480 gtk_action_set_sensitive (action, rich_text && editor_focused);
2481 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2482 gtk_action_set_sensitive (action, rich_text && editor_focused);
2483 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2484 gtk_action_set_sensitive (action, rich_text && editor_focused);
2485 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2486 gtk_action_set_sensitive (action, rich_text && editor_focused);
2487 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2488 gtk_action_set_sensitive (action, rich_text && editor_focused);
2489 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2490 gtk_action_set_sensitive (action, rich_text && editor_focused);
2491 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2492 gtk_action_set_sensitive (action, rich_text && editor_focused);
2493 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2494 gtk_action_set_sensitive (action, rich_text && editor_focused);
2495 widget = priv->font_color_button;
2496 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2497 widget = priv->font_size_toolitem;
2498 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2499 widget = priv->font_face_toolitem;
2500 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2504 setup_insensitive_handlers (ModestMsgEditWindow *window)
2506 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2507 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2510 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2511 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2512 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2513 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2514 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2515 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2516 widget = priv->font_color_button;
2517 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2518 widget = priv->font_size_toolitem;
2519 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2520 widget = priv->font_face_toolitem;
2521 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2526 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2528 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2531 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2532 gtk_action_set_sensitive (action, can_undo);
2536 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2538 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2541 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/RedoMenu");
2542 gtk_action_set_sensitive (action, can_redo);
2546 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2549 GtkTextIter match_start, match_end;
2551 if (image_id == NULL)
2554 gtk_text_buffer_get_start_iter (buffer, &iter);
2556 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2557 GSList *tags = gtk_text_iter_get_tags (&match_start);
2559 for (node = tags; node != NULL; node = g_slist_next (node)) {
2560 GtkTextTag *tag = (GtkTextTag *) node->data;
2561 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2562 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2563 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2565 offset = gtk_text_iter_get_offset (&match_start);
2566 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2567 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2571 gtk_text_iter_forward_char (&iter);
2576 msg_body_focus (GtkWidget *focus,
2577 GdkEventFocus *event,
2581 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2586 recpt_field_changed (GtkTextBuffer *buffer,
2587 ModestMsgEditWindow *editor)
2589 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2590 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2591 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2592 gboolean dim = FALSE;
2595 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2596 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2597 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2599 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2600 gtk_text_buffer_get_char_count (cc_buffer) +
2601 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2603 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2604 gtk_action_set_sensitive (action, !dim);
2605 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2606 gtk_action_set_sensitive (action, !dim);
2610 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2612 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2616 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2618 gboolean rich_text, editor_focused;
2620 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2621 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2622 editor_focused = gtk_widget_is_focus (priv->msg_body);
2625 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2626 else if (!editor_focused)
2627 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2631 reset_modified (ModestMsgEditWindow *editor)
2633 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2634 GtkTextBuffer *buffer;
2636 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2637 gtk_text_buffer_set_modified (buffer, FALSE);
2638 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2639 gtk_text_buffer_set_modified (buffer, FALSE);
2640 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2641 gtk_text_buffer_set_modified (buffer, FALSE);
2642 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2646 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2648 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2649 GtkTextBuffer *buffer;
2651 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2652 if (gtk_text_buffer_get_modified (buffer))
2654 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2655 if (gtk_text_buffer_get_modified (buffer))
2657 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2658 if (gtk_text_buffer_get_modified (buffer))
2660 if (gtk_text_buffer_get_modified (priv->text_buffer))
2667 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
2669 ModestMsgEditWindowPrivate *priv = NULL;
2671 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2672 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2674 /* check if there's no recipient added */
2675 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2676 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2677 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2678 /* no recipient contents, then select contacts */
2679 modest_msg_edit_window_open_addressbook (window, NULL);
2683 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook))
2685 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook))
2687 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook))
2690 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2697 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2698 ModestMsgEditWindow *window)
2700 modest_msg_edit_window_offer_attach_file (window);
2704 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2706 ModestMsgEditWindow *window)
2708 ModestWindowPrivate *parent_priv;
2709 ModestMsgEditWindowPrivate *priv;
2711 gboolean has_selection;
2713 GList *selected_attachments = NULL;
2714 gint n_att_selected = 0;
2716 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2717 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2719 if (!GTK_WIDGET_VISIBLE (window))
2721 has_selection = gtk_clipboard_wait_for_targets (clipboard, NULL, NULL);
2722 focused = gtk_window_get_focus (GTK_WINDOW (window));
2724 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2725 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2726 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2727 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2729 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2730 n_att_selected = g_list_length (selected_attachments);
2731 g_list_free (selected_attachments);
2733 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2734 gtk_action_set_sensitive (action, n_att_selected == 1);
2736 update_paste_dimming (window);
2740 update_window_title (ModestMsgEditWindow *window)
2742 ModestMsgEditWindowPrivate *priv = NULL;
2743 const gchar *subject;
2745 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2746 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2747 if (subject == NULL || subject[0] == '\0')
2748 subject = _("mail_va_new_email");
2750 gtk_window_set_title (GTK_WINDOW (window), subject);
2755 subject_field_changed (GtkEditable *editable,
2756 ModestMsgEditWindow *window)
2758 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2759 update_window_title (window);
2760 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2764 message_is_empty (ModestMsgEditWindow *window)
2766 ModestMsgEditWindowPrivate *priv = NULL;
2768 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2769 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2771 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
2772 * so we can ignore markup.
2774 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
2777 count = gtk_text_buffer_get_char_count (buf);
2783 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2786 ModestMsgEditWindowPrivate *priv = NULL;
2788 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2789 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2791 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2794 gtk_widget_show_all (priv->find_toolbar);
2795 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2797 gtk_widget_hide_all (priv->find_toolbar);
2798 gtk_widget_grab_focus (priv->msg_body);
2804 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2806 GtkTextIter *match_start,
2807 GtkTextIter *match_end)
2809 GtkTextIter end_iter;
2810 gchar *str_casefold;
2813 gchar *range_casefold;
2816 gboolean result = FALSE;
2823 gtk_text_iter_forward_to_end (&end_iter);
2825 str_casefold = g_utf8_casefold (str, -1);
2826 str_chars_n = strlen (str);
2828 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2829 range_casefold = g_utf8_casefold (range_text, -1);
2830 range_chars_n = strlen (range_casefold);
2832 if (range_chars_n < str_chars_n) {
2833 g_free (str_casefold);
2834 g_free (range_text);
2835 g_free (range_casefold);
2839 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2840 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2841 if (!g_utf8_collate (range_subtext, str_casefold)) {
2842 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2844 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2845 match_start, match_end, NULL);
2846 g_free (found_text);
2848 g_free (range_subtext);
2852 g_free (str_casefold);
2853 g_free (range_text);
2854 g_free (range_casefold);
2861 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2862 ModestMsgEditWindow *window)
2864 gchar *current_search = NULL;
2865 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2867 GtkTextIter selection_start, selection_end;
2868 GtkTextIter match_start, match_end;
2869 gboolean continue_search = FALSE;
2871 if (message_is_empty (window)) {
2872 g_free (priv->last_search);
2873 priv->last_search = NULL;
2874 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
2878 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2879 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2880 g_free (current_search);
2881 g_free (priv->last_search);
2882 priv->last_search = NULL;
2883 /* Information banner about empty search */
2884 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2888 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2889 continue_search = TRUE;
2891 g_free (priv->last_search);
2892 priv->last_search = g_strdup (current_search);
2895 if (continue_search) {
2896 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2897 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2898 &match_start, &match_end);
2900 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2902 GtkTextIter buffer_start;
2903 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2904 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2905 &match_start, &match_end);
2907 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2910 /* Mark as selected the string found in search */
2912 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2913 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2915 g_free (priv->last_search);
2916 priv->last_search = NULL;
2918 g_free (current_search);
2922 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2923 ModestMsgEditWindow *window)
2925 GtkToggleAction *toggle;
2926 ModestWindowPrivate *parent_priv;
2927 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2929 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2930 gtk_toggle_action_set_active (toggle, FALSE);
2935 update_paste_dimming (ModestMsgEditWindow *window)
2937 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2938 GtkAction *action = NULL;
2939 GtkClipboard *clipboard = NULL;
2940 ModestEmailClipboard *e_clipboard;
2944 focused = gtk_window_get_focus (GTK_WINDOW (window));
2946 e_clipboard = modest_runtime_get_email_clipboard ();
2947 if (!modest_email_clipboard_cleared (e_clipboard)) {
2950 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2951 active = gtk_clipboard_wait_is_text_available (clipboard);
2955 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2959 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2960 gtk_action_set_sensitive (action, active);
2965 update_select_all_dimming (ModestMsgEditWindow *window)
2968 gboolean dimmed = FALSE;
2970 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2972 focused = gtk_window_get_focus (GTK_WINDOW (window));
2973 if (GTK_IS_ENTRY (focused)) {
2974 const gchar *current_text;
2975 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
2976 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
2977 } else if (GTK_IS_TEXT_VIEW (focused)) {
2978 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
2979 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
2980 } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
2983 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
2984 gtk_action_set_sensitive (action, !dimmed);
2988 update_zoom_dimming (ModestMsgEditWindow *window)
2991 gboolean dimmed = FALSE;
2993 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2995 focused = gtk_window_get_focus (GTK_WINDOW (window));
2996 dimmed = ! WP_IS_TEXT_VIEW (focused);
2997 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2998 gtk_action_set_sensitive (action, !dimmed);
3002 edit_menu_activated (GtkAction *action,
3005 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3007 update_select_all_dimming (window);
3008 update_paste_dimming (window);
3011 view_menu_activated (GtkAction *action,
3014 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3016 update_zoom_dimming (window);
3020 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3022 ModestMsgEditWindowPrivate *priv;
3024 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3029 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3032 ModestMsgEditWindowPrivate *priv;
3034 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3040 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3043 ModestMsgEditWindowPrivate *priv;
3044 TnyHeader *header = NULL;
3046 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3047 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3049 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3050 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3052 if (priv->draft_msg != NULL) {
3053 header = tny_msg_get_header (priv->draft_msg);
3054 if (TNY_IS_HEADER (header)) {
3055 modest_window_mgr_unregister_header (mgr, header);
3057 g_object_unref (priv->draft_msg);
3060 if (draft != NULL) {
3061 g_object_ref (draft);
3062 header = tny_msg_get_header (draft);
3063 if (TNY_IS_HEADER (header))
3064 modest_window_mgr_register_header (mgr, header);
3067 priv->draft_msg = draft;
3071 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3072 GtkTextIter *start, GtkTextIter *end,
3075 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3076 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3079 if (tag == NULL+13) return;
3080 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3081 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3082 replace_with_attachments (window, priv->attachments);
3087 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3090 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3092 g_return_if_fail (TNY_IS_MIME_PART (part));
3093 priv->attachments = g_list_prepend (priv->attachments, part);
3094 g_object_ref (part);
3095 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part);
3096 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3097 gtk_widget_show_all (priv->attachments_caption);
3098 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);