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-address-book.h"
59 #include "modest-text-utils.h"
60 #include <tny-simple-list.h>
61 #include <wptextview.h>
62 #include <wptextbuffer.h>
63 #include "modest-scroll-area.h"
65 #include "modest-hildon-includes.h"
66 #include "widgets/modest-msg-edit-window-ui.h"
67 #include <libgnomevfs/gnome-vfs-mime.h>
70 #define DEFAULT_FONT_SIZE 3
71 #define DEFAULT_FONT 2
72 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
73 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
74 #define DEFAULT_MAIN_VBOX_SPACING 6
75 #define SUBJECT_MAX_LENGTH 1000
77 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
78 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
79 static void modest_msg_edit_window_finalize (GObject *obj);
81 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
82 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
83 static void send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
84 static void style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
85 static void setup_insensitive_handlers (ModestMsgEditWindow *editor);
86 static void reset_modified (ModestMsgEditWindow *editor);
87 static gboolean is_modified (ModestMsgEditWindow *editor);
89 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
90 static void text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata);
91 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
92 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
93 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
94 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
96 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
98 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
100 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
101 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
102 GdkEventWindowState *event,
104 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
105 ModestRecptEditor *editor);
106 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
107 ModestMsgEditWindow *window);
109 /* ModestWindow methods implementation */
110 static void modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom);
111 static gdouble modest_msg_edit_window_get_zoom (ModestWindow *window);
112 static gboolean modest_msg_edit_window_zoom_minus (ModestWindow *window);
113 static gboolean modest_msg_edit_window_zoom_plus (ModestWindow *window);
114 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
115 gboolean show_toolbar);
116 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
118 ModestMsgEditWindow *window);
119 static void modest_msg_edit_window_system_clipboard_owner_change (GtkClipboard *clipboard,
121 ModestMsgEditWindow *window);
122 static void update_window_title (ModestMsgEditWindow *window);
123 static void update_dimmed (ModestMsgEditWindow *window);
124 static void update_paste_dimming (ModestMsgEditWindow *window);
127 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
128 ModestMsgEditWindow *window);
129 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
130 ModestMsgEditWindow *window);
132 /* list my signals */
139 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
140 struct _ModestMsgEditWindowPrivate {
142 GtkWidget *header_box;
144 ModestPairList *from_field_protos;
145 GtkWidget *from_field;
149 GtkWidget *bcc_field;
150 GtkWidget *subject_field;
151 GtkWidget *attachments_view;
152 GtkWidget *priority_icon;
153 GtkWidget *add_attachment_button;
155 GtkWidget *cc_caption;
156 GtkWidget *bcc_caption;
157 GtkWidget *attachments_caption;
159 GtkTextBuffer *text_buffer;
161 GtkWidget *font_size_toolitem;
162 GtkWidget *font_face_toolitem;
163 GtkWidget *font_color_button;
164 GSList *font_items_group;
165 GtkWidget *font_tool_button_label;
166 GSList *size_items_group;
167 GtkWidget *size_tool_button_label;
169 GtkWidget *find_toolbar;
176 TnyHeaderFlags priority_flags;
180 gulong clipboard_change_handler_id;
181 gulong system_clipboard_change_handler_id;
186 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
187 MODEST_TYPE_MSG_EDIT_WINDOW, \
188 ModestMsgEditWindowPrivate))
190 static GtkWindowClass *parent_class = NULL;
192 /* uncomment the following if you have defined any signals */
193 /* static guint signals[LAST_SIGNAL] = {0}; */
196 modest_msg_edit_window_get_type (void)
198 static GType my_type = 0;
200 static const GTypeInfo my_info = {
201 sizeof(ModestMsgEditWindowClass),
202 NULL, /* base init */
203 NULL, /* base finalize */
204 (GClassInitFunc) modest_msg_edit_window_class_init,
205 NULL, /* class finalize */
206 NULL, /* class data */
207 sizeof(ModestMsgEditWindow),
209 (GInstanceInitFunc) modest_msg_edit_window_init,
212 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
213 "ModestMsgEditWindow",
216 wp_text_buffer_library_init ();
222 save_state (ModestWindow *self)
224 modest_widget_memory_save (modest_runtime_get_conf(),
225 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
230 restore_settings (ModestMsgEditWindow *self)
232 modest_widget_memory_restore (modest_runtime_get_conf(),
233 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
238 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
240 GObjectClass *gobject_class;
241 ModestWindowClass *modest_window_class;
242 gobject_class = (GObjectClass*) klass;
243 modest_window_class = (ModestWindowClass*) klass;
245 parent_class = g_type_class_peek_parent (klass);
246 gobject_class->finalize = modest_msg_edit_window_finalize;
248 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
249 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
250 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
251 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
252 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
254 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
256 modest_window_class->save_state_func = save_state;
260 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
262 ModestMsgEditWindowPrivate *priv;
263 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
265 priv->msg_body = NULL;
266 priv->from_field = NULL;
267 priv->to_field = NULL;
268 priv->cc_field = NULL;
269 priv->bcc_field = NULL;
270 priv->subject_field = NULL;
271 priv->attachments = NULL;
273 priv->zoom_level = 1.0;
275 priv->cc_caption = NULL;
276 priv->bcc_caption = NULL;
278 priv->priority_flags = 0;
280 priv->find_toolbar = NULL;
282 priv->draft_msg = NULL;
283 priv->clipboard_change_handler_id = 0;
284 priv->system_clipboard_change_handler_id = 0;
288 /* FIXME: this is a dup from the one in gtk/ */
291 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
293 static ModestPairList*
294 get_transports (void)
296 GSList *transports = NULL;
298 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
299 GSList *accounts = modest_account_mgr_account_names (account_mgr,
300 TRUE /* only enabled accounts. */);
302 GSList *cursor = accounts;
304 gchar *account_name = cursor->data;
305 gchar *from_string = NULL;
307 from_string = modest_account_mgr_get_from_string (account_mgr,
311 if (from_string && account_name) {
312 gchar *name = account_name;
313 ModestPair *pair = modest_pair_new ((gpointer) name,
314 (gpointer) from_string , TRUE);
315 transports = g_slist_prepend (transports, pair);
318 cursor = cursor->next;
320 g_slist_free (accounts); /* only free the accounts, not the elements,
321 * because they are used in the pairlist */
327 init_window (ModestMsgEditWindow *obj)
329 GtkWidget *from_caption, *to_caption, *subject_caption;
330 GtkWidget *main_vbox;
331 ModestMsgEditWindowPrivate *priv;
333 GtkSizeGroup *size_group;
335 GtkWidget *scroll_area;
336 GtkWidget *subject_box;
337 GtkWidget *attachment_icon;
338 GtkWidget *window_box;
340 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
342 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
344 /* Note: This ModestPairList* must exist for as long as the combo
345 * that uses it, because the ModestComboBox uses the ID opaquely,
346 * so it can't know how to manage its memory. */
347 priv->from_field_protos = get_transports ();
349 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
351 priv->to_field = modest_recpt_editor_new ();
352 priv->cc_field = modest_recpt_editor_new ();
353 priv->bcc_field = modest_recpt_editor_new ();
354 subject_box = gtk_hbox_new (FALSE, 0);
355 priv->priority_icon = gtk_image_new ();
356 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
357 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
358 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
359 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
360 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
361 priv->add_attachment_button = gtk_button_new ();
362 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
363 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
364 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
365 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
366 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
367 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
368 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
369 priv->attachments_view = modest_attachments_view_new (NULL);
371 priv->header_box = gtk_vbox_new (FALSE, 0);
373 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
374 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
375 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
376 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
377 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
378 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
379 g_object_unref (size_group);
381 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
382 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
383 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
384 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
385 gtk_size_group_add_widget (size_group, priv->subject_field);
386 gtk_size_group_add_widget (size_group, priv->attachments_view);
387 g_object_unref (size_group);
389 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
390 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
391 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
392 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
393 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
394 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
395 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
398 priv->msg_body = wp_text_view_new ();
399 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
400 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
401 g_object_set (priv->text_buffer, "font_scale", 1.0, NULL);
402 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
403 /* gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
404 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
406 priv->find_toolbar = hildon_find_toolbar_new (NULL);
407 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
409 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
410 G_CALLBACK (text_buffer_refresh_attributes), obj);
411 g_signal_connect (G_OBJECT (priv->text_buffer), "delete-range",
412 G_CALLBACK (text_buffer_delete_range), obj);
413 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
414 G_CALLBACK (text_buffer_can_undo), obj);
415 g_signal_connect (G_OBJECT (obj), "window-state-event",
416 G_CALLBACK (modest_msg_edit_window_window_state_event),
418 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
419 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
420 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
421 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
422 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
423 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
425 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
426 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
428 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
429 G_CALLBACK (msg_body_focus), obj);
430 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
431 G_CALLBACK (msg_body_focus), obj);
432 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
433 "changed", G_CALLBACK (recpt_field_changed), obj);
434 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
435 "changed", G_CALLBACK (recpt_field_changed), obj);
436 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
437 "changed", G_CALLBACK (recpt_field_changed), obj);
438 recpt_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
439 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
441 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
442 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
444 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
445 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
446 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
448 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
450 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
451 frame = gtk_frame_new (NULL);
452 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
454 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
455 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
456 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
458 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL)) {
459 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
460 gtk_widget_hide (priv->cc_caption);
462 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL)) {
463 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
464 gtk_widget_hide (priv->bcc_caption);
467 window_box = gtk_vbox_new (FALSE, 0);
468 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
469 gtk_box_pack_end (GTK_BOX (window_box), priv->find_toolbar, FALSE, FALSE, 0);
470 gtk_container_add (GTK_CONTAINER(obj), window_box);
471 scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
472 gtk_container_add (GTK_CONTAINER (frame), scroll_area);
473 gtk_container_set_focus_vadjustment (GTK_CONTAINER (scroll_area),
474 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
476 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
477 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
478 priv->system_clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
479 G_CALLBACK (modest_msg_edit_window_system_clipboard_owner_change), obj);
485 modest_msg_edit_window_finalize (GObject *obj)
487 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
489 if (priv->clipboard_change_handler_id > 0) {
490 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), priv->clipboard_change_handler_id);
491 priv->clipboard_change_handler_id = 0;
494 if (priv->system_clipboard_change_handler_id > 0) {
495 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
496 priv->system_clipboard_change_handler_id);
497 priv->system_clipboard_change_handler_id = 0;
500 /* This had to stay alive for as long as the combobox that used it: */
501 modest_pair_list_free (priv->from_field_protos);
503 G_OBJECT_CLASS(parent_class)->finalize (obj);
507 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMsgEditWindow *self)
509 GtkWidget *close_dialog;
510 ModestMsgEditWindowPrivate *priv;
513 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
514 modest_window_save_state (MODEST_WINDOW (self));
515 if (is_modified (self)) {
516 close_dialog = hildon_note_new_confirmation (GTK_WINDOW (self), _("mcen_nc_no_email_message_modified_save_changes"));
517 response = gtk_dialog_run (GTK_DIALOG (close_dialog));
518 gtk_widget_destroy (close_dialog);
520 if (response != GTK_RESPONSE_CANCEL) {
521 modest_ui_actions_on_save_to_drafts (NULL, self);
524 /* /\* remove old message from drafts *\/ */
525 /* if (priv->draft_msg) { */
526 /* TnyHeader *header = tny_msg_get_header (priv->draft_msg); */
527 /* TnyAccount *account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(), */
529 /* TNY_ACCOUNT_TYPE_STORE); */
530 /* TnyFolder *folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS); */
531 /* g_return_val_if_fail (TNY_IS_HEADER (header), FALSE); */
532 /* g_return_val_if_fail (TNY_IS_FOLDER (folder), FALSE); */
533 /* tny_folder_remove_msg (folder, header, NULL); */
534 /* g_object_unref (folder); */
535 /* g_object_unref (header); */
536 /* g_object_unref (priv->draft_msg); */
537 /* priv->draft_msg = NULL; */
539 gtk_widget_destroy (GTK_WIDGET (self));
545 menubar_to_menu (GtkUIManager *ui_manager)
547 GtkWidget *main_menu;
551 /* Create new main menu */
552 main_menu = gtk_menu_new();
554 /* Get the menubar from the UI manager */
555 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
557 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
561 menu = GTK_WIDGET (iter->data);
562 gtk_widget_reparent(menu, main_menu);
564 iter = g_list_next (iter);
571 set_msg (ModestMsgEditWindow *self, TnyMsg *msg)
574 const gchar *to, *cc, *bcc, *subject;
576 ModestMsgEditWindowPrivate *priv;
578 TnyHeaderFlags priority_flags;
580 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
581 g_return_if_fail (TNY_IS_MSG (msg));
583 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
585 header = tny_msg_get_header (msg);
586 to = tny_header_get_to (header);
587 cc = tny_header_get_cc (header);
588 bcc = tny_header_get_bcc (header);
589 subject = tny_header_get_subject (header);
590 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
593 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
595 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
597 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
599 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
600 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
603 update_window_title (self);
605 /* gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
606 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
607 body = modest_tny_msg_get_body (msg, TRUE);
609 if ((body == NULL)||(body[0] == '\0')) {
611 body = modest_text_utils_convert_to_html ("");
613 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
614 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
617 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
620 /* Get the default format required from configuration */
621 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
622 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
625 /* Set the default focus depending on having already a To: field or not */
626 if ((!to)||(*to == '\0')) {
627 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
629 gtk_widget_grab_focus (priv->msg_body);
632 /* TODO: lower priority, select in the From: combo to the
633 value that comes from msg <- not sure, should it be
636 /* Add attachments to the view */
637 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
638 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
639 if (priv->attachments == NULL) {
640 gtk_widget_hide (priv->attachments_caption);
642 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
643 gtk_widget_show_all (priv->attachments_caption);
646 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
647 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
649 reset_modified (self);
651 update_dimmed (self);
652 text_buffer_can_undo (priv->text_buffer, FALSE, self);
654 priv->draft_msg = msg;
658 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
661 GList *item_children, *node;
662 GtkWidget *bin_child;
664 bin_child = gtk_bin_get_child (GTK_BIN(item));
666 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
668 for (node = item_children; node != NULL; node = g_list_next (node)) {
669 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
670 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
673 g_list_free (item_children);
677 menu_tool_button_dont_expand (GtkMenuToolButton *item)
680 GList *item_children, *node;
682 box = gtk_bin_get_child (GTK_BIN (item));
683 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
684 item_children = gtk_container_get_children (GTK_CONTAINER (box));
686 for (node = item_children; node != NULL; node = g_list_next (node)) {
687 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
688 if (GTK_IS_TOGGLE_BUTTON (node->data))
689 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
690 else if (GTK_IS_BUTTON (node->data))
691 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
693 g_list_free (item_children);
698 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
700 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
701 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
702 GtkWidget *placeholder;
703 GtkWidget *tool_item;
708 GtkWidget *sizes_menu;
709 GtkWidget *fonts_menu;
710 GSList *radio_group = NULL;
715 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
716 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
718 /* should we hide the toolbar? */
719 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
720 gtk_widget_hide (parent_priv->toolbar);
722 /* Font color placeholder */
723 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
724 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
727 tool_item = GTK_WIDGET (gtk_tool_item_new ());
728 priv->font_color_button = hildon_color_button_new ();
729 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
730 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
731 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
732 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
733 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
734 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
735 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
737 /* Font size and face placeholder */
738 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
739 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
741 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
742 priv->size_tool_button_label = gtk_label_new (NULL);
743 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
744 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
745 size_text,"</span>", NULL);
746 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
748 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
749 sizes_menu = gtk_menu_new ();
750 priv->size_items_group = NULL;
752 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
753 GtkWidget *size_menu_item;
755 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
756 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
757 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
758 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
759 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
760 gtk_widget_show (size_menu_item);
762 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
766 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
767 GtkWidget *item = (GtkWidget *) node->data;
768 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
772 priv->size_items_group = g_slist_reverse (priv->size_items_group);
773 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
774 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
775 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
776 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
777 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
778 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
779 priv->font_size_toolitem = tool_item;
782 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
783 priv->font_tool_button_label = gtk_label_new (NULL);
784 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
785 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
787 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
788 fonts_menu = gtk_menu_new ();
789 priv->font_items_group = NULL;
791 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
792 GtkWidget *font_menu_item;
793 GtkWidget *child_label;
795 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
796 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
797 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
798 wp_get_font_name (font_index), "</span>", NULL);
799 gtk_label_set_markup (GTK_LABEL (child_label), markup);
802 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
803 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
804 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
805 gtk_widget_show (font_menu_item);
807 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
810 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
811 GtkWidget *item = (GtkWidget *) node->data;
812 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
815 priv->font_items_group = g_slist_reverse (priv->font_items_group);
816 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
817 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
818 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
819 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
820 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
821 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
822 priv->font_face_toolitem = tool_item;
824 /* Set expand and homogeneous for remaining items */
825 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
826 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
827 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
828 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
829 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
830 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
831 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
832 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
833 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
841 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name)
844 ModestWindowPrivate *parent_priv;
845 ModestMsgEditWindowPrivate *priv;
846 GtkActionGroup *action_group;
847 GError *error = NULL;
848 GdkPixbuf *window_icon = NULL;
851 gboolean prefer_formatted;
853 ModestPair *account_pair = NULL;
855 g_return_val_if_fail (msg, NULL);
856 g_return_val_if_fail (account_name, NULL);
858 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
860 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
861 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
863 parent_priv->ui_manager = gtk_ui_manager_new();
864 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
865 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
867 /* Add common actions */
868 gtk_action_group_add_actions (action_group,
869 modest_msg_edit_action_entries,
870 G_N_ELEMENTS (modest_msg_edit_action_entries),
872 gtk_action_group_add_toggle_actions (action_group,
873 modest_msg_edit_toggle_action_entries,
874 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
876 gtk_action_group_add_radio_actions (action_group,
877 modest_msg_edit_alignment_radio_action_entries,
878 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
880 G_CALLBACK (modest_ui_actions_on_change_justify),
882 gtk_action_group_add_radio_actions (action_group,
883 modest_msg_edit_zoom_action_entries,
884 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
886 G_CALLBACK (modest_ui_actions_on_change_zoom),
888 gtk_action_group_add_radio_actions (action_group,
889 modest_msg_edit_priority_action_entries,
890 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
892 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
894 gtk_action_group_add_radio_actions (action_group,
895 modest_msg_edit_file_format_action_entries,
896 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
897 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
898 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
900 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
901 g_object_unref (action_group);
903 /* Load the UI definition */
904 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
907 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
908 g_clear_error (&error);
911 /* Add accelerators */
912 gtk_window_add_accel_group (GTK_WINDOW (obj),
913 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
916 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
917 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
920 init_window (MODEST_MSG_EDIT_WINDOW(obj));
922 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
924 gtk_window_set_icon_from_file (GTK_WINDOW(obj), MODEST_APP_ICON, NULL);
926 g_signal_connect (G_OBJECT(obj), "delete-event",
927 G_CALLBACK(on_delete_event), obj);
929 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
931 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
933 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
935 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
936 if (account_pair != NULL)
937 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
939 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg);
941 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
943 /* Set window icon */
944 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
945 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
947 /* Dim at start clipboard actions */
948 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
949 gtk_action_set_sensitive (action, FALSE);
950 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
951 gtk_action_set_sensitive (action, FALSE);
953 /* set initial state of cc and bcc */
954 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
955 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
956 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
957 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
958 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
959 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
961 /* Setup the file format */
962 conf = modest_runtime_get_conf ();
963 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
965 g_clear_error (&error);
966 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
968 file_format = (prefer_formatted) ?
969 MODEST_FILE_FORMAT_FORMATTED_TEXT :
970 MODEST_FILE_FORMAT_PLAIN_TEXT;
971 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
973 update_paste_dimming (MODEST_MSG_EDIT_WINDOW (obj));
975 return (ModestWindow*) obj;
979 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
981 GString **string_buffer = (GString **) user_data;
983 *string_buffer = g_string_append (*string_buffer, buffer);
989 * @result: A new string which should be freed with g_free().
992 get_formatted_data (ModestMsgEditWindow *edit_window)
994 ModestMsgEditWindowPrivate *priv;
995 GString *string_buffer = g_string_new ("");
997 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
999 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1001 return g_string_free (string_buffer, FALSE);
1006 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1009 const gchar *account_name;
1010 ModestMsgEditWindowPrivate *priv;
1012 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1014 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1016 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1017 g_return_val_if_fail (account_name, NULL);
1020 /* don't free these (except from) */
1021 data = g_slice_new0 (MsgData);
1022 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1024 data->account_name = g_strdup (account_name);
1025 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1026 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1027 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1028 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1029 if (priv->draft_msg) {
1030 data->draft_msg = g_object_ref (priv->draft_msg);
1032 data->draft_msg = NULL;
1035 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1037 gtk_text_buffer_get_bounds (buf, &b, &e);
1038 data->plain_body = g_strdup (gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE)); /* returns a copy */
1040 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1041 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1043 data->html_body = NULL;
1045 data->attachments = priv->attachments; /* TODO: copy and free ? */
1046 data->priority_flags = priv->priority_flags;
1051 /* TODO: We must duplicate this implementation for GNOME and Maemo, but that is unwise. */
1053 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1056 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1064 g_free (data->subject);
1065 g_free (data->plain_body);
1066 g_free (data->html_body);
1067 if (data->draft_msg != NULL) {
1068 g_object_unref (data->draft_msg);
1069 data->draft_msg = NULL;
1071 g_free (data->account_name);
1073 /* TODO: Free data->attachments? */
1075 g_slice_free (MsgData, data);
1079 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1082 ModestMsgEditWindowPrivate *priv = NULL;
1083 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1085 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1087 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1089 return MODEST_MSG_EDIT_FORMAT_HTML;
1091 return MODEST_MSG_EDIT_FORMAT_TEXT;
1095 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1096 ModestMsgEditFormat format)
1098 ModestMsgEditWindowPrivate *priv;
1100 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1101 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1104 case MODEST_MSG_EDIT_FORMAT_HTML:
1105 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1107 case MODEST_MSG_EDIT_FORMAT_TEXT:
1108 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1111 g_return_if_reached ();
1115 ModestMsgEditFormatState *
1116 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1118 ModestMsgEditFormatState *format_state = NULL;
1119 ModestMsgEditWindowPrivate *priv;
1120 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1122 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1123 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1125 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1127 format_state = g_new0 (ModestMsgEditFormatState, 1);
1128 format_state->bold = buffer_format->bold&0x1;
1129 format_state->italics = buffer_format->italic&0x1;
1130 format_state->bullet = buffer_format->bullet&0x1;
1131 format_state->color = buffer_format->color;
1132 format_state->font_size = buffer_format->font_size;
1133 format_state->font_family = wp_get_font_name (buffer_format->font);
1134 format_state->justification = buffer_format->justification;
1135 g_free (buffer_format);
1137 return format_state;
1142 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1143 const ModestMsgEditFormatState *format_state)
1145 ModestMsgEditWindowPrivate *priv;
1146 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1147 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1148 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1149 g_return_if_fail (format_state != NULL);
1151 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1152 gtk_widget_grab_focus (priv->msg_body);
1153 buffer_format->bold = (format_state->bold != FALSE);
1154 buffer_format->italic = (format_state->italics != FALSE);
1155 buffer_format->color = format_state->color;
1156 buffer_format->font_size = format_state->font_size;
1157 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1158 buffer_format->justification = format_state->justification;
1159 buffer_format->bullet = format_state->bullet;
1161 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1163 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1164 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1165 buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
1166 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1167 buffer_format->cs.font = (buffer_format->font != current_format->font);
1168 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1169 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1171 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1172 if (buffer_format->cs.bold) {
1173 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1175 if (buffer_format->cs.italic) {
1176 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1178 if (buffer_format->cs.color) {
1179 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1181 if (buffer_format->cs.font_size) {
1182 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->font_size));
1184 if (buffer_format->cs.justification) {
1185 switch (buffer_format->justification) {
1186 case GTK_JUSTIFY_LEFT:
1187 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1189 case GTK_JUSTIFY_CENTER:
1190 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1192 case GTK_JUSTIFY_RIGHT:
1193 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1200 if (buffer_format->cs.font) {
1201 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->font));
1203 if (buffer_format->cs.bullet) {
1204 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((int)buffer_format->bullet));
1206 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1207 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1209 g_free (current_format);
1214 toggle_action_set_active_block_notify (GtkToggleAction *action,
1217 GSList *proxies = NULL;
1219 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1220 proxies != NULL; proxies = g_slist_next (proxies)) {
1221 GtkWidget *widget = (GtkWidget *) proxies->data;
1222 gtk_action_block_activate_from (GTK_ACTION (action), widget);
1225 gtk_toggle_action_set_active (action, value);
1227 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1228 proxies != NULL; proxies = g_slist_next (proxies)) {
1229 GtkWidget *widget = (GtkWidget *) proxies->data;
1230 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
1235 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1237 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1239 ModestWindowPrivate *parent_priv;
1240 ModestMsgEditWindowPrivate *priv;
1241 GtkWidget *new_size_menuitem;
1242 GtkWidget *new_font_menuitem;
1244 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1245 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1247 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1248 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1249 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1250 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1252 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1253 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1254 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1257 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1259 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1260 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1262 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1263 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1265 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1266 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1268 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1269 G_CALLBACK (modest_msg_edit_window_color_button_change),
1271 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1272 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1273 G_CALLBACK (modest_msg_edit_window_color_button_change),
1276 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1277 buffer_format->font_size))->data);
1278 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1282 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1283 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1284 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1286 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1287 G_CALLBACK (modest_msg_edit_window_size_change),
1289 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1290 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1291 G_CALLBACK (modest_msg_edit_window_size_change),
1295 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1296 buffer_format->font))->data);
1297 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1301 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1302 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1303 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1305 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1306 G_CALLBACK (modest_msg_edit_window_font_change),
1308 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1309 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1310 G_CALLBACK (modest_msg_edit_window_font_change),
1314 g_free (buffer_format);
1320 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1323 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1324 ModestMsgEditWindowPrivate *priv;
1325 GtkWidget *dialog = NULL;
1327 const GdkColor *new_color = NULL;
1329 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1330 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1332 #ifdef MODEST_HILDON_VERSION_0
1333 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1334 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1336 dialog = hildon_color_chooser_new ();
1337 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1338 #endif /*MODEST_HILDON_VERSION_0*/
1339 g_free (buffer_format);
1341 response = gtk_dialog_run (GTK_DIALOG (dialog));
1343 case GTK_RESPONSE_OK: {
1344 #ifdef MODEST_HILDON_VERSION_0
1345 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1348 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1350 #endif /*MODEST_HILDON_VERSION_0*/
1357 gtk_widget_destroy (dialog);
1359 if (new_color != NULL)
1360 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1365 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1368 ModestMsgEditWindowPrivate *priv;
1369 GtkWidget *dialog = NULL;
1371 GdkColor *old_color = NULL;
1372 const GdkColor *new_color = NULL;
1374 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1375 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1377 #ifdef MODEST_HILDON_VERSION_0
1378 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1379 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1381 dialog = hildon_color_chooser_new ();
1382 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1383 #endif /*MODEST_HILDON_VERSION_9*/
1385 response = gtk_dialog_run (GTK_DIALOG (dialog));
1387 case GTK_RESPONSE_OK: {
1388 #ifdef MODEST_HILDON_VERSION_0
1389 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1392 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1394 #endif /*MODEST_HILDON_VERSION_0*/
1400 gtk_widget_destroy (dialog);
1402 if (new_color != NULL)
1403 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1408 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1411 ModestMsgEditWindowPrivate *priv;
1412 GtkWidget *dialog = NULL;
1414 gchar *filename = NULL;
1416 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1418 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1419 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1421 response = gtk_dialog_run (GTK_DIALOG (dialog));
1423 case GTK_RESPONSE_OK:
1424 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1429 gtk_widget_destroy (dialog);
1432 GdkPixbuf *pixbuf = NULL;
1433 GtkTextIter position;
1434 GtkTextMark *insert_mark;
1436 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
1439 GdkPixbufFormat *pixbuf_format;
1441 image_file_id = g_open (filename, O_RDONLY, 0);
1442 pixbuf_format = gdk_pixbuf_get_file_info (filename, NULL, NULL);
1443 if ((image_file_id != -1)&&(pixbuf_format != NULL)) {
1444 TnyMimePart *image_part;
1445 TnyStream *image_stream;
1451 mime_types = gdk_pixbuf_format_get_mime_types (pixbuf_format);
1452 if ((mime_types != NULL) && (mime_types[0] != NULL)) {
1453 mime_type = mime_types[0];
1455 mime_type = "image/unknown";
1457 image_part = tny_platform_factory_new_mime_part
1458 (modest_runtime_get_platform_factory ());
1459 image_stream = TNY_STREAM (tny_fs_stream_new (image_file_id));
1461 tny_mime_part_construct_from_stream (image_part, image_stream, mime_type);
1462 g_strfreev (mime_types);
1464 content_id = g_strdup_printf ("%d", priv->last_cid);
1465 tny_mime_part_set_content_id (image_part, content_id);
1466 g_free (content_id);
1469 basename = g_path_get_basename (filename);
1470 tny_mime_part_set_filename (image_part, basename);
1473 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1474 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1475 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (image_part)), pixbuf);
1476 priv->attachments = g_list_prepend (priv->attachments, image_part);
1477 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1479 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1480 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1481 gtk_widget_show_all (priv->attachments_caption);
1482 } else if (image_file_id == -1) {
1483 close (image_file_id);
1492 modest_msg_edit_window_attach_file (ModestMsgEditWindow *window)
1495 ModestMsgEditWindowPrivate *priv;
1496 GtkWidget *dialog = NULL;
1498 GSList *uris = NULL;
1501 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1503 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1504 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1506 response = gtk_dialog_run (GTK_DIALOG (dialog));
1508 case GTK_RESPONSE_OK:
1509 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1514 gtk_widget_destroy (dialog);
1516 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1518 GnomeVFSHandle *handle = NULL;
1519 GnomeVFSResult result;
1521 uri = (const gchar *) uri_node->data;
1522 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1523 if (result == GNOME_VFS_OK) {
1524 TnyMimePart *mime_part;
1526 const gchar *mime_type = NULL;
1530 GnomeVFSFileInfo info;
1532 filename = g_filename_from_uri (uri, NULL, NULL);
1534 if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE) == GNOME_VFS_OK)
1535 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1536 mime_part = tny_platform_factory_new_mime_part
1537 (modest_runtime_get_platform_factory ());
1538 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1540 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1542 content_id = g_strdup_printf ("%d", priv->last_cid);
1543 tny_mime_part_set_content_id (mime_part, content_id);
1544 g_free (content_id);
1547 basename = g_path_get_basename (filename);
1548 tny_mime_part_set_filename (mime_part, basename);
1551 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1552 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1554 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1555 gtk_widget_show_all (priv->attachments_caption);
1556 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1561 g_slist_foreach (uris, (GFunc) g_free, NULL);
1562 g_slist_free (uris);
1566 modest_msg_edit_window_attach_file_noninteractive (
1567 ModestMsgEditWindow *window,
1568 const gchar *file_uri)
1571 ModestMsgEditWindowPrivate *priv;
1573 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1578 /* TODO: We should probably try to use only the URI,
1579 * instead of using a filename.
1581 gchar* filename = g_filename_from_uri (file_uri, NULL, NULL);
1583 g_warning("%s: g_filename_from_uri(%s) failed.\n", __FUNCTION__, file_uri);
1586 file_id = g_open (filename, O_RDONLY, 0);
1587 if (file_id != -1) {
1588 TnyMimePart *mime_part;
1590 const gchar *mime_type;
1594 mime_type = gnome_vfs_get_file_mime_type_fast (filename, NULL);
1595 mime_part = tny_platform_factory_new_mime_part
1596 (modest_runtime_get_platform_factory ());
1597 stream = TNY_STREAM (tny_fs_stream_new (file_id));
1599 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1601 content_id = g_strdup_printf ("%d", priv->last_cid);
1602 tny_mime_part_set_content_id (mime_part, content_id);
1603 g_free (content_id);
1606 basename = g_path_get_basename (filename);
1607 tny_mime_part_set_filename (mime_part, basename);
1610 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1611 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1613 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1614 gtk_widget_show_all (priv->attachments_caption);
1615 } else if (file_id == -1) {
1617 g_warning("file to be attached does not exist: %s", filename);
1625 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1628 ModestMsgEditWindowPrivate *priv;
1629 gboolean clean_list = FALSE;
1631 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1632 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1634 if (att_list == NULL) {
1635 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1639 if (att_list == NULL) {
1640 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1642 GtkWidget *confirmation_dialog = NULL;
1643 gboolean dialog_response;
1645 gchar *message = NULL;
1646 const gchar *filename = NULL;
1648 if (att_list->next == NULL) {
1649 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1653 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1654 att_list->next == NULL), filename);
1655 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1657 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1658 gtk_widget_destroy (confirmation_dialog);
1659 if (!dialog_response) {
1661 g_list_free (att_list);
1664 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1666 for (node = att_list; node != NULL; node = g_list_next (node)) {
1667 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1668 const gchar *att_id;
1669 priv->attachments = g_list_remove (priv->attachments, mime_part);
1671 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1673 if (priv->attachments == NULL)
1674 gtk_widget_hide (priv->attachments_caption);
1675 att_id = tny_mime_part_get_content_id (mime_part);
1677 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1679 g_object_unref (mime_part);
1680 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1685 g_list_free (att_list);
1689 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1692 ModestMsgEditWindowPrivate *priv;
1693 GdkColor *new_color;
1694 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1696 #ifdef MODEST_HILDON_VERSION_0
1697 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1700 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1702 #endif /*MODEST_HILDON_VERSION_0*/
1704 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1706 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1711 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1714 ModestMsgEditWindowPrivate *priv;
1715 gint new_size_index;
1716 ModestMsgEditWindow *window;
1719 window = MODEST_MSG_EDIT_WINDOW (userdata);
1720 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1721 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1723 if (gtk_check_menu_item_get_active (menu_item)) {
1725 WPTextBufferFormat format;
1727 memset (&format, 0, sizeof (format));
1728 wp_text_buffer_get_current_state (WP_TEXT_BUFFER (priv->text_buffer), &format);
1730 label = gtk_bin_get_child (GTK_BIN (menu_item));
1732 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1733 format.cs.font_size = TRUE;
1734 format.cs.text_position = TRUE;
1735 format.cs.font = TRUE;
1736 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1737 wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format);
1739 /* if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, */
1740 /* (gpointer) wp_get_font_size_index (new_size_index, 12))) */
1741 /* wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body)); */
1743 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1744 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1745 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1751 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1754 ModestMsgEditWindowPrivate *priv;
1755 gint new_font_index;
1756 ModestMsgEditWindow *window;
1759 window = MODEST_MSG_EDIT_WINDOW (userdata);
1760 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1761 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1763 if (gtk_check_menu_item_get_active (menu_item)) {
1766 label = gtk_bin_get_child (GTK_BIN (menu_item));
1768 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1770 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1771 (gpointer) new_font_index))
1772 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1774 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1775 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1776 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1782 modest_msg_edit_window_set_zoom (ModestWindow *window,
1785 ModestMsgEditWindowPrivate *priv;
1787 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1789 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1790 priv->zoom_level = zoom;
1791 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom);
1795 modest_msg_edit_window_get_zoom (ModestWindow *window)
1797 ModestMsgEditWindowPrivate *priv;
1799 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1801 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1802 return priv->zoom_level;
1806 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1808 ModestWindowPrivate *parent_priv;
1809 GtkRadioAction *zoom_radio_action;
1810 GSList *group, *node;
1812 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1813 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1814 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1816 group = gtk_radio_action_get_group (zoom_radio_action);
1818 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1819 hildon_banner_show_information (NULL, NULL, _("ckct_ib_max_zoom_level_reached"));
1823 for (node = group; node != NULL; node = g_slist_next (node)) {
1824 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1825 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1833 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1835 ModestWindowPrivate *parent_priv;
1836 GtkRadioAction *zoom_radio_action;
1837 GSList *group, *node;
1839 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1840 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1841 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1843 group = gtk_radio_action_get_group (zoom_radio_action);
1845 for (node = group; node != NULL; node = g_slist_next (node)) {
1846 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1847 if (node->next != NULL) {
1848 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1851 hildon_banner_show_information (NULL, NULL, _("ckct_ib_min_zoom_level_reached"));
1859 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1861 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1862 ModestWindowPrivate *parent_priv;
1863 ModestWindowMgr *mgr;
1864 gboolean is_fullscreen;
1865 GtkAction *fs_toggle_action;
1868 mgr = modest_runtime_get_window_mgr ();
1869 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1871 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1873 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1874 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1875 if (is_fullscreen != active)
1876 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1884 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
1886 ModestWindowPrivate *parent_priv;
1887 GtkAction *fs_toggle_action;
1890 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1892 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1893 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
1894 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
1898 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
1901 ModestMsgEditWindowPrivate *priv = NULL;
1902 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1904 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1905 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1907 gtk_widget_show (priv->cc_caption);
1909 gtk_widget_hide (priv->cc_caption);
1910 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
1914 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
1917 ModestMsgEditWindowPrivate *priv = NULL;
1918 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1920 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1921 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1923 gtk_widget_show (priv->bcc_caption);
1925 gtk_widget_hide (priv->bcc_caption);
1926 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
1930 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
1931 ModestRecptEditor *editor)
1933 ModestMsgEditWindowPrivate *priv;
1935 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1936 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
1937 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1939 if (editor == NULL) {
1940 GtkWidget *view_focus;
1941 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
1943 /* This code should be kept in sync with ModestRecptEditor. The
1944 textview inside the recpt editor is the one that really gets the
1945 focus. As it's inside a scrolled window, and this one inside the
1946 hbox recpt editor inherits from, we'll need to go up in the
1947 hierarchy to know if the text view is part of the recpt editor
1948 or if it's a different text entry */
1950 if (gtk_widget_get_parent (view_focus)) {
1951 GtkWidget *first_parent;
1953 first_parent = gtk_widget_get_parent (view_focus);
1954 if (gtk_widget_get_parent (first_parent) &&
1955 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
1956 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
1961 editor = MODEST_RECPT_EDITOR (priv->to_field);
1965 modest_address_book_select_addresses (editor);
1970 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
1972 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1974 modest_msg_edit_window_open_addressbook (window, NULL);
1978 modest_msg_edit_window_show_toolbar (ModestWindow *self,
1979 gboolean show_toolbar)
1981 ModestWindowPrivate *parent_priv;
1983 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1984 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1986 /* FIXME: we can not just use the code of
1987 modest_msg_edit_window_setup_toolbar because it has a
1988 mixture of both initialization and creation code. */
1991 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1993 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1997 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
1998 TnyHeaderFlags priority_flags)
2000 ModestMsgEditWindowPrivate *priv;
2001 ModestWindowPrivate *parent_priv;
2003 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2005 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2006 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2007 priority_flags = priority_flags & (TNY_HEADER_FLAG_HIGH_PRIORITY);
2009 if (priv->priority_flags != priority_flags) {
2010 GtkAction *priority_action = NULL;
2012 priv->priority_flags = priority_flags;
2014 switch (priority_flags) {
2015 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2016 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2017 gtk_widget_show (priv->priority_icon);
2018 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2019 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2021 case TNY_HEADER_FLAG_LOW_PRIORITY:
2022 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2023 gtk_widget_show (priv->priority_icon);
2024 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2025 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2028 gtk_widget_hide (priv->priority_icon);
2029 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2030 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2033 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2034 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2039 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2042 ModestMsgEditWindowPrivate *priv;
2043 gint current_format;
2045 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2047 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2049 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2050 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2052 if (current_format != file_format) {
2053 switch (file_format) {
2054 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2055 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2057 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2061 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2062 response = gtk_dialog_run (GTK_DIALOG (dialog));
2063 gtk_widget_destroy (dialog);
2064 if (response == GTK_RESPONSE_OK)
2065 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2069 update_dimmed (window);
2074 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2077 ModestMsgEditWindowPrivate *priv;
2078 WPTextBufferFormat oldfmt, fmt;
2079 gint old_position = 0;
2083 GdkColor *color = NULL;
2084 gboolean bold, bold_set, italic, italic_set;
2085 gboolean underline, underline_set;
2086 gboolean strikethrough, strikethrough_set;
2087 gboolean position_set;
2088 gboolean font_size_set, font_set, color_set;
2091 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2092 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2094 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2096 /* First we get the currently selected font information */
2097 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2098 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2100 switch (oldfmt.text_position) {
2101 case TEXT_POSITION_NORMAL:
2104 case TEXT_POSITION_SUPERSCRIPT:
2112 g_object_set (G_OBJECT (dialog),
2113 "bold", oldfmt.bold != FALSE,
2114 "bold-set", !oldfmt.cs.bold,
2115 "underline", oldfmt.underline != FALSE,
2116 "underline-set", !oldfmt.cs.underline,
2117 "italic", oldfmt.italic != FALSE,
2118 "italic-set", !oldfmt.cs.italic,
2119 "strikethrough", oldfmt.strikethrough != FALSE,
2120 "strikethrough-set", !oldfmt.cs.strikethrough,
2121 "color", &oldfmt.color,
2122 "color-set", !oldfmt.cs.color,
2123 "size", wp_font_size[oldfmt.font_size],
2124 "size-set", !oldfmt.cs.font_size,
2125 "position", old_position,
2126 "position-set", !oldfmt.cs.text_position,
2127 "family", wp_get_font_name (oldfmt.font),
2128 "family-set", !oldfmt.cs.font,
2131 gtk_widget_show_all (dialog);
2132 response = gtk_dialog_run (GTK_DIALOG (dialog));
2133 if (response == GTK_RESPONSE_OK) {
2135 g_object_get( dialog,
2137 "bold-set", &bold_set,
2138 "underline", &underline,
2139 "underline-set", &underline_set,
2141 "italic-set", &italic_set,
2142 "strikethrough", &strikethrough,
2143 "strikethrough-set", &strikethrough_set,
2145 "color-set", &color_set,
2147 "size-set", &font_size_set,
2148 "family", &font_name,
2149 "family-set", &font_set,
2150 "position", &position,
2151 "position-set", &position_set,
2156 if (response == GTK_RESPONSE_OK) {
2157 memset(&fmt, 0, sizeof(fmt));
2163 fmt.italic = italic;
2164 fmt.cs.italic = TRUE;
2166 if (underline_set) {
2167 fmt.underline = underline;
2168 fmt.cs.underline = TRUE;
2170 if (strikethrough_set) {
2171 fmt.strikethrough = strikethrough;
2172 fmt.cs.strikethrough = TRUE;
2177 ? TEXT_POSITION_NORMAL
2178 : ( ( position == 1 )
2179 ? TEXT_POSITION_SUPERSCRIPT
2180 : TEXT_POSITION_SUBSCRIPT );
2181 fmt.cs.text_position = TRUE;
2185 fmt.cs.color = TRUE;
2188 fmt.font = wp_get_font_index(font_name,
2193 if (font_size_set) {
2194 fmt.font_size = wp_get_font_size_index(
2195 font_size, DEFAULT_FONT_SIZE);
2196 fmt.cs.font_size = TRUE;
2198 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2200 gtk_widget_destroy (dialog);
2202 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2206 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2208 ModestMsgEditWindowPrivate *priv;
2210 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2211 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2213 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2215 update_dimmed (window);
2220 update_dimmed (ModestMsgEditWindow *window)
2222 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2223 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2227 gboolean editor_focused;
2229 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2230 editor_focused = gtk_widget_is_focus (priv->msg_body);
2232 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2233 gtk_action_set_sensitive (action, rich_text && editor_focused);
2234 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2235 gtk_action_set_sensitive (action, rich_text && editor_focused);
2236 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2237 gtk_action_set_sensitive (action, rich_text && editor_focused);
2238 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2239 gtk_action_set_sensitive (action, rich_text && editor_focused);
2240 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2241 gtk_action_set_sensitive (action, rich_text && editor_focused);
2242 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2243 gtk_action_set_sensitive (action, rich_text && editor_focused);
2244 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2245 gtk_action_set_sensitive (action, rich_text && editor_focused);
2246 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2247 gtk_action_set_sensitive (action, rich_text && editor_focused);
2248 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2249 gtk_action_set_sensitive (action, rich_text && editor_focused);
2250 widget = priv->font_color_button;
2251 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2252 widget = priv->font_size_toolitem;
2253 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2254 widget = priv->font_face_toolitem;
2255 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2259 setup_insensitive_handlers (ModestMsgEditWindow *window)
2261 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2262 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2265 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2266 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2267 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2268 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2270 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2271 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2272 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2273 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2274 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2275 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2276 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2277 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2278 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2279 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2280 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2281 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2282 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2283 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2284 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2285 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2286 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2287 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2288 widget = priv->font_color_button;
2289 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2290 widget = priv->font_size_toolitem;
2291 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2292 widget = priv->font_face_toolitem;
2293 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2298 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2300 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2303 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2304 gtk_action_set_sensitive (action, can_undo);
2308 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2311 GtkTextIter match_start, match_end;
2313 if (image_id == NULL)
2316 gtk_text_buffer_get_start_iter (buffer, &iter);
2318 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2319 GSList *tags = gtk_text_iter_get_tags (&match_start);
2321 for (node = tags; node != NULL; node = g_slist_next (node)) {
2322 GtkTextTag *tag = (GtkTextTag *) node->data;
2323 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2324 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2325 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2327 offset = gtk_text_iter_get_offset (&match_start);
2328 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2329 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2333 gtk_text_iter_forward_char (&iter);
2338 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2340 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2341 GtkTextIter real_start, real_end;
2342 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2344 if (gtk_text_iter_compare (start, end) > 0) {
2348 real_start = *start;
2352 GSList *tags = gtk_text_iter_get_tags (&real_start);
2354 for (node = tags; node != NULL; node = g_slist_next (node)) {
2355 GtkTextTag *tag = (GtkTextTag *) node->data;
2356 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2357 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2359 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2361 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2364 } while (gtk_text_iter_forward_char (&real_start)&&
2365 (gtk_text_iter_compare (&real_start, &real_end)<=0));
2369 msg_body_focus (GtkWidget *focus,
2370 GdkEventFocus *event,
2374 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2379 recpt_field_changed (GtkTextBuffer *buffer,
2380 ModestMsgEditWindow *editor)
2382 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2383 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2384 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2385 gboolean dim = FALSE;
2388 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2389 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2390 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2392 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2393 gtk_text_buffer_get_char_count (cc_buffer) +
2394 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2396 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2397 gtk_action_set_sensitive (action, !dim);
2398 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2399 gtk_action_set_sensitive (action, !dim);
2403 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2405 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2409 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2411 gboolean rich_text, editor_focused;
2413 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2414 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2415 editor_focused = gtk_widget_is_focus (priv->msg_body);
2418 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2419 else if (!editor_focused)
2420 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2424 reset_modified (ModestMsgEditWindow *editor)
2426 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2427 GtkTextBuffer *buffer;
2429 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2430 gtk_text_buffer_set_modified (buffer, FALSE);
2431 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2432 gtk_text_buffer_set_modified (buffer, FALSE);
2433 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2434 gtk_text_buffer_set_modified (buffer, FALSE);
2435 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2439 is_modified (ModestMsgEditWindow *editor)
2441 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2442 GtkTextBuffer *buffer;
2444 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2445 if (gtk_text_buffer_get_modified (buffer))
2447 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2448 if (gtk_text_buffer_get_modified (buffer))
2450 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2451 if (gtk_text_buffer_get_modified (buffer))
2453 if (gtk_text_buffer_get_modified (priv->text_buffer))
2460 modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
2462 ModestMsgEditWindowPrivate *priv = NULL;
2464 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2465 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2467 /* check if there's no recipient added */
2468 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2469 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2470 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2471 /* no recipient contents, then select contacts */
2472 modest_msg_edit_window_open_addressbook (window, NULL);
2476 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
2478 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
2480 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
2483 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2490 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2491 ModestMsgEditWindow *window)
2493 modest_msg_edit_window_attach_file (window);
2497 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2499 ModestMsgEditWindow *window)
2501 ModestWindowPrivate *parent_priv;
2506 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2507 selection = gtk_clipboard_wait_for_text (clipboard);
2508 focused = gtk_window_get_focus (GTK_WINDOW (window));
2510 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2511 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2512 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2513 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2515 update_paste_dimming (window);
2519 update_window_title (ModestMsgEditWindow *window)
2521 ModestMsgEditWindowPrivate *priv = NULL;
2522 const gchar *subject;
2524 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2525 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2526 if (subject == NULL || subject[0] == '\0')
2527 subject = _("mail_va_new_email");
2529 gtk_window_set_title (GTK_WINDOW (window), subject);
2534 subject_field_changed (GtkEditable *editable,
2535 ModestMsgEditWindow *window)
2537 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2538 update_window_title (window);
2539 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2543 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2546 ModestMsgEditWindowPrivate *priv = NULL;
2548 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2549 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2551 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2553 gtk_widget_show_all (priv->find_toolbar);
2554 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2556 gtk_widget_hide_all (priv->find_toolbar);
2557 gtk_widget_grab_focus (priv->msg_body);
2563 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2564 ModestMsgEditWindow *window)
2566 gchar *current_search = NULL;
2567 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2569 GtkTextIter selection_start, selection_end;
2570 GtkTextIter match_start, match_end;
2572 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2573 if ((current_search == NULL) && (strcmp (current_search, "") == 0)) {
2574 g_free (current_search);
2578 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2579 result = gtk_text_iter_forward_search (&selection_end, current_search, GTK_TEXT_SEARCH_VISIBLE_ONLY, &match_start, &match_end, NULL);
2581 GtkTextIter buffer_start;
2582 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2583 result = gtk_text_iter_forward_search (&buffer_start, current_search, GTK_TEXT_SEARCH_VISIBLE_ONLY, &match_start, &match_end, &selection_start);
2586 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2587 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2589 /* TODO: warning about non succesful search */
2591 g_free (current_search);
2595 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2596 ModestMsgEditWindow *window)
2598 GtkToggleAction *toggle;
2599 ModestWindowPrivate *parent_priv;
2600 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2602 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2603 gtk_toggle_action_set_active (toggle, FALSE);
2608 update_paste_dimming (ModestMsgEditWindow *window)
2610 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2611 GtkAction *action = NULL;
2612 GtkClipboard *clipboard = NULL;
2614 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2616 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2617 gtk_action_set_sensitive (action, gtk_clipboard_wait_is_text_available (clipboard));
2622 modest_msg_edit_window_system_clipboard_owner_change (GtkClipboard *clipboard,
2624 ModestMsgEditWindow *window)
2626 update_paste_dimming (window);