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 update_window_title (ModestMsgEditWindow *window);
120 static void update_dimmed (ModestMsgEditWindow *window);
123 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
124 ModestMsgEditWindow *window);
125 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
126 ModestMsgEditWindow *window);
129 /* list my signals */
136 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
137 struct _ModestMsgEditWindowPrivate {
139 GtkWidget *header_box;
141 ModestPairList *from_field_protos;
142 GtkWidget *from_field;
146 GtkWidget *bcc_field;
147 GtkWidget *subject_field;
148 GtkWidget *attachments_view;
149 GtkWidget *priority_icon;
150 GtkWidget *add_attachment_button;
152 GtkWidget *cc_caption;
153 GtkWidget *bcc_caption;
154 GtkWidget *attachments_caption;
156 GtkTextBuffer *text_buffer;
158 GtkWidget *font_size_toolitem;
159 GtkWidget *font_face_toolitem;
160 GtkWidget *font_color_button;
161 GSList *font_items_group;
162 GtkWidget *font_tool_button_label;
163 GSList *size_items_group;
164 GtkWidget *size_tool_button_label;
166 GtkWidget *find_toolbar;
173 TnyHeaderFlags priority_flags;
177 gulong clipboard_change_handler_id;
182 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
183 MODEST_TYPE_MSG_EDIT_WINDOW, \
184 ModestMsgEditWindowPrivate))
186 static GtkWindowClass *parent_class = NULL;
188 /* uncomment the following if you have defined any signals */
189 /* static guint signals[LAST_SIGNAL] = {0}; */
192 modest_msg_edit_window_get_type (void)
194 static GType my_type = 0;
196 static const GTypeInfo my_info = {
197 sizeof(ModestMsgEditWindowClass),
198 NULL, /* base init */
199 NULL, /* base finalize */
200 (GClassInitFunc) modest_msg_edit_window_class_init,
201 NULL, /* class finalize */
202 NULL, /* class data */
203 sizeof(ModestMsgEditWindow),
205 (GInstanceInitFunc) modest_msg_edit_window_init,
208 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
209 "ModestMsgEditWindow",
212 wp_text_buffer_library_init ();
218 save_state (ModestWindow *self)
220 modest_widget_memory_save (modest_runtime_get_conf(),
221 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
226 restore_settings (ModestMsgEditWindow *self)
228 modest_widget_memory_restore (modest_runtime_get_conf(),
229 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
234 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
236 GObjectClass *gobject_class;
237 ModestWindowClass *modest_window_class;
238 gobject_class = (GObjectClass*) klass;
239 modest_window_class = (ModestWindowClass*) klass;
241 parent_class = g_type_class_peek_parent (klass);
242 gobject_class->finalize = modest_msg_edit_window_finalize;
244 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
245 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
246 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
247 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
248 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
250 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
252 modest_window_class->save_state_func = save_state;
256 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
258 ModestMsgEditWindowPrivate *priv;
259 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
261 priv->msg_body = NULL;
262 priv->from_field = NULL;
263 priv->to_field = NULL;
264 priv->cc_field = NULL;
265 priv->bcc_field = NULL;
266 priv->subject_field = NULL;
267 priv->attachments = NULL;
269 priv->zoom_level = 1.0;
271 priv->cc_caption = NULL;
272 priv->bcc_caption = NULL;
274 priv->priority_flags = 0;
276 priv->find_toolbar = NULL;
278 priv->draft_msg = NULL;
279 priv->clipboard_change_handler_id = 0;
283 /* FIXME: this is a dup from the one in gtk/ */
286 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
288 static ModestPairList*
289 get_transports (void)
291 GSList *transports = NULL;
293 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
294 GSList *accounts = modest_account_mgr_account_names (account_mgr,
295 TRUE /* only enabled accounts. */);
297 GSList *cursor = accounts;
299 const gchar *account_name = cursor->data;
300 gchar *from_string = NULL;
302 from_string = modest_account_mgr_get_from_string (account_mgr,
306 if (from_string && account_name) {
307 gchar *name = g_strdup (account_name);
308 ModestPair *pair = modest_pair_new ((gpointer) name,
309 (gpointer) from_string , TRUE);
310 transports = g_slist_prepend (transports, pair);
313 cursor = cursor->next;
315 g_slist_free (accounts);
321 init_window (ModestMsgEditWindow *obj)
323 GtkWidget *from_caption, *to_caption, *subject_caption;
324 GtkWidget *main_vbox;
325 ModestMsgEditWindowPrivate *priv;
327 GtkSizeGroup *size_group;
329 GtkWidget *scroll_area;
330 GtkWidget *subject_box;
331 GtkWidget *attachment_icon;
332 GtkWidget *window_box;
334 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
336 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
338 /* Note: This ModestPairList* must exist for as long as the combo
339 * that uses it, because the ModestComboBox uses the ID opaquely,
340 * so it can't know how to manage its memory. */
341 priv->from_field_protos = get_transports ();
343 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
345 priv->to_field = modest_recpt_editor_new ();
346 priv->cc_field = modest_recpt_editor_new ();
347 priv->bcc_field = modest_recpt_editor_new ();
348 subject_box = gtk_hbox_new (FALSE, 0);
349 priv->priority_icon = gtk_image_new ();
350 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
351 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
352 g_object_set (G_OBJECT (priv->subject_field), "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL);
353 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
354 priv->add_attachment_button = gtk_button_new ();
355 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
356 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
357 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
358 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
359 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
360 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
361 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
362 priv->attachments_view = modest_attachments_view_new (NULL);
364 priv->header_box = gtk_vbox_new (FALSE, 0);
366 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
367 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
368 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
369 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
370 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
371 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
372 g_object_unref (size_group);
374 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
375 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
376 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
377 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
378 gtk_size_group_add_widget (size_group, priv->subject_field);
379 gtk_size_group_add_widget (size_group, priv->attachments_view);
380 g_object_unref (size_group);
382 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
383 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
384 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
385 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
386 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
387 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
388 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
391 priv->msg_body = wp_text_view_new ();
392 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
393 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
394 g_object_set (priv->text_buffer, "font_scale", 1.0, NULL);
395 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
396 /* gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
397 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
399 priv->find_toolbar = hildon_find_toolbar_new (NULL);
400 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
402 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
403 G_CALLBACK (text_buffer_refresh_attributes), obj);
404 g_signal_connect (G_OBJECT (priv->text_buffer), "delete-range",
405 G_CALLBACK (text_buffer_delete_range), obj);
406 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
407 G_CALLBACK (text_buffer_can_undo), obj);
408 g_signal_connect (G_OBJECT (obj), "window-state-event",
409 G_CALLBACK (modest_msg_edit_window_window_state_event),
411 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
412 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
413 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
414 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
415 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
416 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
418 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
419 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
421 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
422 G_CALLBACK (msg_body_focus), obj);
423 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
424 G_CALLBACK (msg_body_focus), obj);
425 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
426 "changed", G_CALLBACK (recpt_field_changed), obj);
427 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
428 "changed", G_CALLBACK (recpt_field_changed), obj);
429 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
430 "changed", G_CALLBACK (recpt_field_changed), obj);
431 recpt_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
432 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
434 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
435 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
437 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
438 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
439 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
441 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
443 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
444 frame = gtk_frame_new (NULL);
445 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
447 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
448 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
449 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
451 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL)) {
452 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
453 gtk_widget_hide (priv->cc_caption);
455 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL)) {
456 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
457 gtk_widget_hide (priv->bcc_caption);
460 window_box = gtk_vbox_new (FALSE, 0);
461 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
462 gtk_box_pack_end (GTK_BOX (window_box), priv->find_toolbar, FALSE, FALSE, 0);
463 gtk_container_add (GTK_CONTAINER(obj), window_box);
464 scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
465 gtk_container_add (GTK_CONTAINER (frame), scroll_area);
466 gtk_container_set_focus_vadjustment (GTK_CONTAINER (scroll_area),
467 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
469 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
470 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
476 modest_msg_edit_window_finalize (GObject *obj)
478 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
480 if (priv->clipboard_change_handler_id > 0) {
481 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), priv->clipboard_change_handler_id);
482 priv->clipboard_change_handler_id = 0;
485 /* This had to stay alive for as long as the combobox that used it: */
486 modest_pair_list_free (priv->from_field_protos);
488 G_OBJECT_CLASS(parent_class)->finalize (obj);
492 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMsgEditWindow *self)
494 GtkWidget *close_dialog;
495 ModestMsgEditWindowPrivate *priv;
498 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
499 modest_window_save_state (MODEST_WINDOW (self));
500 if (is_modified (self)) {
501 close_dialog = hildon_note_new_confirmation (GTK_WINDOW (self), _("mcen_nc_no_email_message_modified_save_changes"));
502 response = gtk_dialog_run (GTK_DIALOG (close_dialog));
503 gtk_widget_destroy (close_dialog);
505 if (response != GTK_RESPONSE_CANCEL) {
506 modest_ui_actions_on_save_to_drafts (NULL, self);
509 /* /\* remove old message from drafts *\/ */
510 /* if (priv->draft_msg) { */
511 /* TnyHeader *header = tny_msg_get_header (priv->draft_msg); */
512 /* TnyAccount *account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(), */
514 /* TNY_ACCOUNT_TYPE_STORE); */
515 /* TnyFolder *folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS); */
516 /* g_return_val_if_fail (TNY_IS_HEADER (header), FALSE); */
517 /* g_return_val_if_fail (TNY_IS_FOLDER (folder), FALSE); */
518 /* tny_folder_remove_msg (folder, header, NULL); */
519 /* g_object_unref (folder); */
520 /* g_object_unref (header); */
521 /* g_object_unref (priv->draft_msg); */
522 /* priv->draft_msg = NULL; */
524 gtk_widget_destroy (GTK_WIDGET (self));
530 menubar_to_menu (GtkUIManager *ui_manager)
532 GtkWidget *main_menu;
536 /* Create new main menu */
537 main_menu = gtk_menu_new();
539 /* Get the menubar from the UI manager */
540 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
542 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
546 menu = GTK_WIDGET (iter->data);
547 gtk_widget_reparent(menu, main_menu);
549 iter = g_list_next (iter);
556 set_msg (ModestMsgEditWindow *self, TnyMsg *msg)
559 const gchar *to, *cc, *bcc, *subject;
561 ModestMsgEditWindowPrivate *priv;
564 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
565 g_return_if_fail (TNY_IS_MSG (msg));
567 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
569 header = tny_msg_get_header (msg);
570 to = tny_header_get_to (header);
571 cc = tny_header_get_cc (header);
572 bcc = tny_header_get_bcc (header);
573 subject = tny_header_get_subject (header);
576 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
578 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
580 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
582 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
584 update_window_title (self);
586 /* gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
587 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
588 body = modest_tny_msg_get_body (msg, TRUE);
590 if ((body == NULL)||(body[0] == '\0')) {
592 body = modest_text_utils_convert_to_html ("");
594 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
595 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
598 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
601 /* Get the default format required from configuration */
602 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
603 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
606 /* Set the default focus depending on having already a To: field or not */
607 if ((!to)||(*to == '\0')) {
608 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
610 gtk_widget_grab_focus (priv->msg_body);
613 /* TODO: lower priority, select in the From: combo to the
614 value that comes from msg <- not sure, should it be
617 /* Add attachments to the view */
618 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
619 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
620 if (priv->attachments == NULL) {
621 gtk_widget_hide (priv->attachments_caption);
623 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
624 gtk_widget_show_all (priv->attachments_caption);
627 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
628 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
630 reset_modified (self);
632 update_dimmed (self);
633 text_buffer_can_undo (priv->text_buffer, FALSE, self);
635 priv->draft_msg = msg;
639 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
642 GList *item_children, *node;
643 GtkWidget *bin_child;
645 bin_child = gtk_bin_get_child (GTK_BIN(item));
647 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
649 for (node = item_children; node != NULL; node = g_list_next (node)) {
650 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
651 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
654 g_list_free (item_children);
658 menu_tool_button_dont_expand (GtkMenuToolButton *item)
661 GList *item_children, *node;
663 box = gtk_bin_get_child (GTK_BIN (item));
664 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
665 item_children = gtk_container_get_children (GTK_CONTAINER (box));
667 for (node = item_children; node != NULL; node = g_list_next (node)) {
668 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
669 if (GTK_IS_TOGGLE_BUTTON (node->data))
670 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
671 else if (GTK_IS_BUTTON (node->data))
672 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
674 g_list_free (item_children);
679 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
681 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
682 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
683 GtkWidget *placeholder;
684 GtkWidget *tool_item;
689 GtkWidget *sizes_menu;
690 GtkWidget *fonts_menu;
691 GSList *radio_group = NULL;
696 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
697 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
699 /* should we hide the toolbar? */
700 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
701 gtk_widget_hide (parent_priv->toolbar);
703 /* Font color placeholder */
704 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
705 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
708 tool_item = GTK_WIDGET (gtk_tool_item_new ());
709 priv->font_color_button = hildon_color_button_new ();
710 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
711 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
712 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
713 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
714 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
715 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
716 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
718 /* Font size and face placeholder */
719 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
720 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
722 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
723 priv->size_tool_button_label = gtk_label_new (NULL);
724 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
725 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
726 size_text,"</span>", NULL);
727 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
729 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
730 sizes_menu = gtk_menu_new ();
731 priv->size_items_group = NULL;
733 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
734 GtkWidget *size_menu_item;
736 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
737 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
738 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
739 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
740 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
741 gtk_widget_show (size_menu_item);
743 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
747 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
748 GtkWidget *item = (GtkWidget *) node->data;
749 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
753 priv->size_items_group = g_slist_reverse (priv->size_items_group);
754 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
755 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
756 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
757 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
758 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
759 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
760 priv->font_size_toolitem = tool_item;
763 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
764 priv->font_tool_button_label = gtk_label_new (NULL);
765 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
766 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
768 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
769 fonts_menu = gtk_menu_new ();
770 priv->font_items_group = NULL;
772 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
773 GtkWidget *font_menu_item;
774 GtkWidget *child_label;
776 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
777 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
778 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
779 wp_get_font_name (font_index), "</span>", NULL);
780 gtk_label_set_markup (GTK_LABEL (child_label), markup);
783 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
784 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
785 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
786 gtk_widget_show (font_menu_item);
788 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
791 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
792 GtkWidget *item = (GtkWidget *) node->data;
793 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
796 priv->font_items_group = g_slist_reverse (priv->font_items_group);
797 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
798 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
799 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
800 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
801 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
802 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
803 priv->font_face_toolitem = tool_item;
805 /* Set expand and homogeneous for remaining items */
806 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
807 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
808 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
809 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
810 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
811 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
812 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
813 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
814 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
822 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name)
825 ModestWindowPrivate *parent_priv;
826 ModestMsgEditWindowPrivate *priv;
827 GtkActionGroup *action_group;
828 GError *error = NULL;
829 GdkPixbuf *window_icon = NULL;
832 gboolean prefer_formatted;
834 ModestPair *account_pair = NULL;
836 g_return_val_if_fail (msg, NULL);
837 g_return_val_if_fail (account_name, NULL);
839 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
841 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
842 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
844 parent_priv->ui_manager = gtk_ui_manager_new();
845 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
846 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
848 /* Add common actions */
849 gtk_action_group_add_actions (action_group,
850 modest_msg_edit_action_entries,
851 G_N_ELEMENTS (modest_msg_edit_action_entries),
853 gtk_action_group_add_toggle_actions (action_group,
854 modest_msg_edit_toggle_action_entries,
855 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
857 gtk_action_group_add_radio_actions (action_group,
858 modest_msg_edit_alignment_radio_action_entries,
859 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
861 G_CALLBACK (modest_ui_actions_on_change_justify),
863 gtk_action_group_add_radio_actions (action_group,
864 modest_msg_edit_zoom_action_entries,
865 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
867 G_CALLBACK (modest_ui_actions_on_change_zoom),
869 gtk_action_group_add_radio_actions (action_group,
870 modest_msg_edit_priority_action_entries,
871 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
873 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
875 gtk_action_group_add_radio_actions (action_group,
876 modest_msg_edit_file_format_action_entries,
877 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
878 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
879 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
881 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
882 g_object_unref (action_group);
884 /* Load the UI definition */
885 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
888 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
889 g_clear_error (&error);
892 /* Add accelerators */
893 gtk_window_add_accel_group (GTK_WINDOW (obj),
894 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
897 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
898 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
901 init_window (MODEST_MSG_EDIT_WINDOW(obj));
903 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
905 gtk_window_set_icon_from_file (GTK_WINDOW(obj), MODEST_APP_ICON, NULL);
907 g_signal_connect (G_OBJECT(obj), "delete-event",
908 G_CALLBACK(on_delete_event), obj);
910 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
912 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
914 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
916 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
917 if (account_pair != NULL)
918 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
920 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg);
922 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
924 /* Set window icon */
925 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
926 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
928 /* Dim at start clipboard actions */
929 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
930 gtk_action_set_sensitive (action, FALSE);
931 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
932 gtk_action_set_sensitive (action, FALSE);
934 /* set initial state of cc and bcc */
935 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
936 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
937 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
938 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
939 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
940 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
942 /* Setup the file format */
943 conf = modest_runtime_get_conf ();
944 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
946 g_clear_error (&error);
947 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
949 file_format = (prefer_formatted) ?
950 MODEST_FILE_FORMAT_FORMATTED_TEXT :
951 MODEST_FILE_FORMAT_PLAIN_TEXT;
952 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
954 return (ModestWindow*) obj;
958 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
960 GString **string_buffer = (GString **) user_data;
962 *string_buffer = g_string_append (*string_buffer, buffer);
968 * @result: A new string which should be freed with g_free().
971 get_formatted_data (ModestMsgEditWindow *edit_window)
973 ModestMsgEditWindowPrivate *priv;
974 GString *string_buffer = g_string_new ("");
976 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
978 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
980 return g_string_free (string_buffer, FALSE);
985 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
988 const gchar *account_name;
989 ModestMsgEditWindowPrivate *priv;
991 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
993 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
995 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
996 g_return_val_if_fail (account_name, NULL);
999 /* don't free these (except from) */
1000 data = g_slice_new0 (MsgData);
1001 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1003 data->account_name = g_strdup (account_name);
1004 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1005 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1006 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1007 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1008 if (priv->draft_msg) {
1009 data->draft_msg = g_object_ref (priv->draft_msg);
1011 data->draft_msg = NULL;
1014 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1016 gtk_text_buffer_get_bounds (buf, &b, &e);
1017 data->plain_body = g_strdup (gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE)); /* returns a copy */
1019 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1020 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1022 data->html_body = NULL;
1024 data->attachments = priv->attachments; /* TODO: copy and free ? */
1025 data->priority_flags = priv->priority_flags;
1030 /* TODO: We must duplicate this implementation for GNOME and Maemo, but that is unwise. */
1032 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1035 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1043 g_free (data->subject);
1044 g_free (data->plain_body);
1045 g_free (data->html_body);
1046 if (data->draft_msg != NULL) {
1047 g_object_unref (data->draft_msg);
1048 data->draft_msg = NULL;
1050 g_free (data->account_name);
1052 /* TODO: Free data->attachments? */
1054 g_slice_free (MsgData, data);
1058 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1061 ModestMsgEditWindowPrivate *priv = NULL;
1062 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1064 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1066 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1068 return MODEST_MSG_EDIT_FORMAT_HTML;
1070 return MODEST_MSG_EDIT_FORMAT_TEXT;
1074 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1075 ModestMsgEditFormat format)
1077 ModestMsgEditWindowPrivate *priv;
1079 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1080 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1083 case MODEST_MSG_EDIT_FORMAT_HTML:
1084 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1086 case MODEST_MSG_EDIT_FORMAT_TEXT:
1087 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1090 g_return_if_reached ();
1094 ModestMsgEditFormatState *
1095 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1097 ModestMsgEditFormatState *format_state = NULL;
1098 ModestMsgEditWindowPrivate *priv;
1099 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1101 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1102 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1104 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1106 format_state = g_new0 (ModestMsgEditFormatState, 1);
1107 format_state->bold = buffer_format->bold&0x1;
1108 format_state->italics = buffer_format->italic&0x1;
1109 format_state->bullet = buffer_format->bullet&0x1;
1110 format_state->color = buffer_format->color;
1111 format_state->font_size = buffer_format->font_size;
1112 format_state->font_family = wp_get_font_name (buffer_format->font);
1113 format_state->justification = buffer_format->justification;
1114 g_free (buffer_format);
1116 return format_state;
1121 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1122 const ModestMsgEditFormatState *format_state)
1124 ModestMsgEditWindowPrivate *priv;
1125 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1126 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1127 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1128 g_return_if_fail (format_state != NULL);
1130 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1131 gtk_widget_grab_focus (priv->msg_body);
1132 buffer_format->bold = (format_state->bold != FALSE);
1133 buffer_format->italic = (format_state->italics != FALSE);
1134 buffer_format->color = format_state->color;
1135 buffer_format->font_size = format_state->font_size;
1136 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1137 buffer_format->justification = format_state->justification;
1138 buffer_format->bullet = format_state->bullet;
1140 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1142 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1143 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1144 buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
1145 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1146 buffer_format->cs.font = (buffer_format->font != current_format->font);
1147 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1148 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1150 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1151 if (buffer_format->cs.bold) {
1152 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1154 if (buffer_format->cs.italic) {
1155 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1157 if (buffer_format->cs.color) {
1158 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1160 if (buffer_format->cs.font_size) {
1161 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->font_size));
1163 if (buffer_format->cs.justification) {
1164 switch (buffer_format->justification) {
1165 case GTK_JUSTIFY_LEFT:
1166 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1168 case GTK_JUSTIFY_CENTER:
1169 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1171 case GTK_JUSTIFY_RIGHT:
1172 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1179 if (buffer_format->cs.font) {
1180 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->font));
1182 if (buffer_format->cs.bullet) {
1183 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((int)buffer_format->bullet));
1185 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1186 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1188 g_free (current_format);
1193 toggle_action_set_active_block_notify (GtkToggleAction *action,
1196 GSList *proxies = NULL;
1198 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1199 proxies != NULL; proxies = g_slist_next (proxies)) {
1200 GtkWidget *widget = (GtkWidget *) proxies->data;
1201 gtk_action_block_activate_from (GTK_ACTION (action), widget);
1204 gtk_toggle_action_set_active (action, value);
1206 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1207 proxies != NULL; proxies = g_slist_next (proxies)) {
1208 GtkWidget *widget = (GtkWidget *) proxies->data;
1209 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
1214 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1216 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1218 ModestWindowPrivate *parent_priv;
1219 ModestMsgEditWindowPrivate *priv;
1220 GtkWidget *new_size_menuitem;
1221 GtkWidget *new_font_menuitem;
1223 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1224 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1226 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1227 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1228 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1229 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1231 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1232 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1233 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1236 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1238 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1239 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1241 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1242 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1244 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1245 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1247 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1248 G_CALLBACK (modest_msg_edit_window_color_button_change),
1250 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1251 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1252 G_CALLBACK (modest_msg_edit_window_color_button_change),
1255 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1256 buffer_format->font_size))->data);
1257 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1261 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1262 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1263 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1265 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1266 G_CALLBACK (modest_msg_edit_window_size_change),
1268 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1269 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1270 G_CALLBACK (modest_msg_edit_window_size_change),
1274 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1275 buffer_format->font))->data);
1276 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1280 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1281 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1282 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1284 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1285 G_CALLBACK (modest_msg_edit_window_font_change),
1287 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1288 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1289 G_CALLBACK (modest_msg_edit_window_font_change),
1293 g_free (buffer_format);
1299 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1302 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1303 ModestMsgEditWindowPrivate *priv;
1304 GtkWidget *dialog = NULL;
1306 const GdkColor *new_color = NULL;
1308 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1309 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1311 #ifdef MODEST_HILDON_VERSION_0
1312 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1313 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1315 dialog = hildon_color_chooser_new ();
1316 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1317 #endif /*MODEST_HILDON_VERSION_0*/
1318 g_free (buffer_format);
1320 response = gtk_dialog_run (GTK_DIALOG (dialog));
1322 case GTK_RESPONSE_OK: {
1323 #ifdef MODEST_HILDON_VERSION_0
1324 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1327 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1329 #endif /*MODEST_HILDON_VERSION_0*/
1336 gtk_widget_destroy (dialog);
1338 if (new_color != NULL)
1339 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1344 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1347 ModestMsgEditWindowPrivate *priv;
1348 GtkWidget *dialog = NULL;
1350 GdkColor *old_color = NULL;
1351 const GdkColor *new_color = NULL;
1353 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1354 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1356 #ifdef MODEST_HILDON_VERSION_0
1357 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1358 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1360 dialog = hildon_color_chooser_new ();
1361 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1362 #endif /*MODEST_HILDON_VERSION_9*/
1364 response = gtk_dialog_run (GTK_DIALOG (dialog));
1366 case GTK_RESPONSE_OK: {
1367 #ifdef MODEST_HILDON_VERSION_0
1368 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1371 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1373 #endif /*MODEST_HILDON_VERSION_0*/
1379 gtk_widget_destroy (dialog);
1381 if (new_color != NULL)
1382 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1387 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1390 ModestMsgEditWindowPrivate *priv;
1391 GtkWidget *dialog = NULL;
1393 gchar *filename = NULL;
1395 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1397 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1399 response = gtk_dialog_run (GTK_DIALOG (dialog));
1401 case GTK_RESPONSE_OK:
1402 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1407 gtk_widget_destroy (dialog);
1410 GdkPixbuf *pixbuf = NULL;
1411 GtkTextIter position;
1412 GtkTextMark *insert_mark;
1414 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
1417 GdkPixbufFormat *pixbuf_format;
1419 image_file_id = g_open (filename, O_RDONLY, 0);
1420 pixbuf_format = gdk_pixbuf_get_file_info (filename, NULL, NULL);
1421 if ((image_file_id != -1)&&(pixbuf_format != NULL)) {
1422 TnyMimePart *image_part;
1423 TnyStream *image_stream;
1429 mime_types = gdk_pixbuf_format_get_mime_types (pixbuf_format);
1430 if ((mime_types != NULL) && (mime_types[0] != NULL)) {
1431 mime_type = mime_types[0];
1433 mime_type = "image/unknown";
1435 image_part = tny_platform_factory_new_mime_part
1436 (modest_runtime_get_platform_factory ());
1437 image_stream = TNY_STREAM (tny_fs_stream_new (image_file_id));
1439 tny_mime_part_construct_from_stream (image_part, image_stream, mime_type);
1440 g_strfreev (mime_types);
1442 content_id = g_strdup_printf ("%d", priv->last_cid);
1443 tny_mime_part_set_content_id (image_part, content_id);
1444 g_free (content_id);
1447 basename = g_path_get_basename (filename);
1448 tny_mime_part_set_filename (image_part, basename);
1451 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1452 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1453 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (image_part)), pixbuf);
1454 priv->attachments = g_list_prepend (priv->attachments, image_part);
1455 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1457 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1458 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1459 gtk_widget_show_all (priv->attachments_caption);
1460 } else if (image_file_id == -1) {
1461 close (image_file_id);
1470 modest_msg_edit_window_attach_file (ModestMsgEditWindow *window)
1473 ModestMsgEditWindowPrivate *priv;
1474 GtkWidget *dialog = NULL;
1476 gchar *uri = NULL, *filename = NULL;
1478 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1480 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1482 response = gtk_dialog_run (GTK_DIALOG (dialog));
1484 case GTK_RESPONSE_OK:
1485 uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
1486 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1491 gtk_widget_destroy (dialog);
1495 GnomeVFSHandle *handle = NULL;
1496 GnomeVFSResult result;
1498 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1499 if (result == GNOME_VFS_OK) {
1500 TnyMimePart *mime_part;
1502 const gchar *mime_type = NULL;
1505 GnomeVFSFileInfo info;
1507 if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE) == GNOME_VFS_OK)
1508 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1509 mime_part = tny_platform_factory_new_mime_part
1510 (modest_runtime_get_platform_factory ());
1511 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1513 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1515 content_id = g_strdup_printf ("%d", priv->last_cid);
1516 tny_mime_part_set_content_id (mime_part, content_id);
1517 g_free (content_id);
1520 basename = g_path_get_basename (filename);
1521 tny_mime_part_set_filename (mime_part, basename);
1524 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1525 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1527 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1528 gtk_widget_show_all (priv->attachments_caption);
1529 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1536 modest_msg_edit_window_attach_file_noninteractive (
1537 ModestMsgEditWindow *window,
1541 ModestMsgEditWindowPrivate *priv;
1543 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1548 file_id = g_open (filename, O_RDONLY, 0);
1549 if (file_id != -1) {
1550 TnyMimePart *mime_part;
1552 const gchar *mime_type;
1556 mime_type = gnome_vfs_get_file_mime_type_fast (filename, NULL);
1557 mime_part = tny_platform_factory_new_mime_part
1558 (modest_runtime_get_platform_factory ());
1559 stream = TNY_STREAM (tny_fs_stream_new (file_id));
1561 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1563 content_id = g_strdup_printf ("%d", priv->last_cid);
1564 tny_mime_part_set_content_id (mime_part, content_id);
1565 g_free (content_id);
1568 basename = g_path_get_basename (filename);
1569 tny_mime_part_set_filename (mime_part, basename);
1572 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1573 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1575 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1576 gtk_widget_show_all (priv->attachments_caption);
1577 } else if (file_id == -1) {
1579 g_warning("file to be attached does not exist: %s", filename);
1585 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1588 ModestMsgEditWindowPrivate *priv;
1589 gboolean clean_list = FALSE;
1591 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1592 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1594 if (att_list == NULL) {
1595 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1599 if (att_list == NULL) {
1600 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1602 GtkWidget *confirmation_dialog = NULL;
1603 gboolean dialog_response;
1605 if (att_list->next == NULL) {
1606 gchar *message = g_strdup_printf (_("emev_nc_delete_attachment"),
1607 tny_mime_part_get_filename (TNY_MIME_PART (att_list->data)));
1608 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1611 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), _("emev_nc_delete_attachments"));
1613 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1614 gtk_widget_destroy (confirmation_dialog);
1615 if (!dialog_response) {
1617 g_list_free (att_list);
1620 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1622 for (node = att_list; node != NULL; node = g_list_next (node)) {
1623 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1624 const gchar *att_id;
1625 priv->attachments = g_list_remove (priv->attachments, mime_part);
1627 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1629 if (priv->attachments == NULL)
1630 gtk_widget_hide (priv->attachments_caption);
1631 att_id = tny_mime_part_get_content_id (mime_part);
1633 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1635 g_object_unref (mime_part);
1636 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1641 g_list_free (att_list);
1645 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1648 ModestMsgEditWindowPrivate *priv;
1649 GdkColor *new_color;
1650 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1652 #ifdef MODEST_HILDON_VERSION_0
1653 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1656 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1658 #endif /*MODEST_HILDON_VERSION_0*/
1660 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1662 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1667 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1670 ModestMsgEditWindowPrivate *priv;
1671 gint new_size_index;
1672 ModestMsgEditWindow *window;
1675 window = MODEST_MSG_EDIT_WINDOW (userdata);
1676 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1677 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1679 if (gtk_check_menu_item_get_active (menu_item)) {
1681 WPTextBufferFormat format;
1683 memset (&format, 0, sizeof (format));
1684 wp_text_buffer_get_current_state (WP_TEXT_BUFFER (priv->text_buffer), &format);
1686 label = gtk_bin_get_child (GTK_BIN (menu_item));
1688 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1689 format.cs.font_size = TRUE;
1690 format.cs.text_position = TRUE;
1691 format.cs.font = TRUE;
1692 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1693 wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format);
1695 /* if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, */
1696 /* (gpointer) wp_get_font_size_index (new_size_index, 12))) */
1697 /* wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body)); */
1699 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1700 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1701 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1707 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1710 ModestMsgEditWindowPrivate *priv;
1711 gint new_font_index;
1712 ModestMsgEditWindow *window;
1715 window = MODEST_MSG_EDIT_WINDOW (userdata);
1716 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1717 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1719 if (gtk_check_menu_item_get_active (menu_item)) {
1722 label = gtk_bin_get_child (GTK_BIN (menu_item));
1724 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1726 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1727 (gpointer) new_font_index))
1728 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1730 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1731 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1732 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1738 modest_msg_edit_window_set_zoom (ModestWindow *window,
1741 ModestMsgEditWindowPrivate *priv;
1743 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1745 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1746 priv->zoom_level = zoom;
1747 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom);
1751 modest_msg_edit_window_get_zoom (ModestWindow *window)
1753 ModestMsgEditWindowPrivate *priv;
1755 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1757 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1758 return priv->zoom_level;
1762 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1764 ModestWindowPrivate *parent_priv;
1765 GtkRadioAction *zoom_radio_action;
1766 GSList *group, *node;
1768 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1769 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1770 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1772 group = gtk_radio_action_get_group (zoom_radio_action);
1774 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1775 hildon_banner_show_information (NULL, NULL, _("mcen_ib_max_zoom_level"));
1779 for (node = group; node != NULL; node = g_slist_next (node)) {
1780 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1781 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1789 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1791 ModestWindowPrivate *parent_priv;
1792 GtkRadioAction *zoom_radio_action;
1793 GSList *group, *node;
1795 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1796 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1797 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1799 group = gtk_radio_action_get_group (zoom_radio_action);
1801 for (node = group; node != NULL; node = g_slist_next (node)) {
1802 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1803 if (node->next != NULL) {
1804 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1807 hildon_banner_show_information (NULL, NULL, _("mcen_ib_min_zoom_level"));
1815 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1817 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1818 ModestWindowPrivate *parent_priv;
1819 ModestWindowMgr *mgr;
1820 gboolean is_fullscreen;
1821 GtkAction *fs_toggle_action;
1824 mgr = modest_runtime_get_window_mgr ();
1825 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1827 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1829 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1830 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1831 if (is_fullscreen != active)
1832 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1840 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
1842 ModestWindowPrivate *parent_priv;
1843 GtkAction *fs_toggle_action;
1846 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1848 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1849 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
1850 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
1854 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
1857 ModestMsgEditWindowPrivate *priv = NULL;
1858 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1860 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1861 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1863 gtk_widget_show (priv->cc_caption);
1865 gtk_widget_hide (priv->cc_caption);
1866 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
1870 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
1873 ModestMsgEditWindowPrivate *priv = NULL;
1874 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1876 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1877 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1879 gtk_widget_show (priv->bcc_caption);
1881 gtk_widget_hide (priv->bcc_caption);
1882 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
1886 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
1887 ModestRecptEditor *editor)
1889 ModestMsgEditWindowPrivate *priv;
1891 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1892 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
1893 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1895 if (editor == NULL) {
1896 GtkWidget *view_focus;
1897 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
1899 /* This code should be kept in sync with ModestRecptEditor. The
1900 textview inside the recpt editor is the one that really gets the
1901 focus. As it's inside a scrolled window, and this one inside the
1902 hbox recpt editor inherits from, we'll need to go up in the
1903 hierarchy to know if the text view is part of the recpt editor
1904 or if it's a different text entry */
1906 if (gtk_widget_get_parent (view_focus)) {
1907 GtkWidget *first_parent;
1909 first_parent = gtk_widget_get_parent (view_focus);
1910 if (gtk_widget_get_parent (first_parent) &&
1911 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
1912 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
1917 editor = MODEST_RECPT_EDITOR (priv->to_field);
1921 modest_address_book_select_addresses (editor);
1926 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
1928 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1930 modest_msg_edit_window_open_addressbook (window, NULL);
1934 modest_msg_edit_window_show_toolbar (ModestWindow *self,
1935 gboolean show_toolbar)
1937 ModestWindowPrivate *parent_priv;
1939 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1940 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1942 /* FIXME: we can not just use the code of
1943 modest_msg_edit_window_setup_toolbar because it has a
1944 mixture of both initialization and creation code. */
1947 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1949 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1953 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
1954 TnyHeaderFlags priority_flags)
1956 ModestMsgEditWindowPrivate *priv;
1958 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1960 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1961 priority_flags = priority_flags & (TNY_HEADER_FLAG_HIGH_PRIORITY);
1963 if (priv->priority_flags != priority_flags) {
1965 priv->priority_flags = priority_flags;
1967 switch (priority_flags) {
1968 case TNY_HEADER_FLAG_HIGH_PRIORITY:
1969 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
1970 gtk_widget_show (priv->priority_icon);
1972 case TNY_HEADER_FLAG_LOW_PRIORITY:
1973 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
1974 gtk_widget_show (priv->priority_icon);
1977 gtk_widget_hide (priv->priority_icon);
1984 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
1987 ModestMsgEditWindowPrivate *priv;
1988 gint current_format;
1990 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1992 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1994 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
1995 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
1997 if (current_format != file_format) {
1998 switch (file_format) {
1999 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2000 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2002 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2006 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2007 response = gtk_dialog_run (GTK_DIALOG (dialog));
2008 gtk_widget_destroy (dialog);
2009 if (response == GTK_RESPONSE_OK)
2010 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2014 update_dimmed (window);
2019 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2022 ModestMsgEditWindowPrivate *priv;
2023 WPTextBufferFormat oldfmt, fmt;
2024 gint old_position = 0;
2028 GdkColor *color = NULL;
2029 gboolean bold, bold_set, italic, italic_set;
2030 gboolean underline, underline_set;
2031 gboolean strikethrough, strikethrough_set;
2032 gboolean position_set;
2033 gboolean font_size_set, font_set, color_set;
2036 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2037 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2039 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2041 /* First we get the currently selected font information */
2042 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2043 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2045 switch (oldfmt.text_position) {
2046 case TEXT_POSITION_NORMAL:
2049 case TEXT_POSITION_SUPERSCRIPT:
2057 g_object_set (G_OBJECT (dialog),
2058 "bold", oldfmt.bold != FALSE,
2059 "bold-set", !oldfmt.cs.bold,
2060 "underline", oldfmt.underline != FALSE,
2061 "underline-set", !oldfmt.cs.underline,
2062 "italic", oldfmt.italic != FALSE,
2063 "italic-set", !oldfmt.cs.italic,
2064 "strikethrough", oldfmt.strikethrough != FALSE,
2065 "strikethrough-set", !oldfmt.cs.strikethrough,
2066 "color", &oldfmt.color,
2067 "color-set", !oldfmt.cs.color,
2068 "size", wp_font_size[oldfmt.font_size],
2069 "size-set", !oldfmt.cs.font_size,
2070 "position", old_position,
2071 "position-set", !oldfmt.cs.text_position,
2072 "family", wp_get_font_name (oldfmt.font),
2073 "family-set", !oldfmt.cs.font,
2076 gtk_widget_show_all (dialog);
2077 response = gtk_dialog_run (GTK_DIALOG (dialog));
2078 if (response == GTK_RESPONSE_OK) {
2080 g_object_get( dialog,
2082 "bold-set", &bold_set,
2083 "underline", &underline,
2084 "underline-set", &underline_set,
2086 "italic-set", &italic_set,
2087 "strikethrough", &strikethrough,
2088 "strikethrough-set", &strikethrough_set,
2090 "color-set", &color_set,
2092 "size-set", &font_size_set,
2093 "family", &font_name,
2094 "family-set", &font_set,
2095 "position", &position,
2096 "position-set", &position_set,
2101 if (response == GTK_RESPONSE_OK) {
2102 memset(&fmt, 0, sizeof(fmt));
2108 fmt.italic = italic;
2109 fmt.cs.italic = TRUE;
2111 if (underline_set) {
2112 fmt.underline = underline;
2113 fmt.cs.underline = TRUE;
2115 if (strikethrough_set) {
2116 fmt.strikethrough = strikethrough;
2117 fmt.cs.strikethrough = TRUE;
2122 ? TEXT_POSITION_NORMAL
2123 : ( ( position == 1 )
2124 ? TEXT_POSITION_SUPERSCRIPT
2125 : TEXT_POSITION_SUBSCRIPT );
2126 fmt.cs.text_position = TRUE;
2130 fmt.cs.color = TRUE;
2133 fmt.font = wp_get_font_index(font_name,
2138 if (font_size_set) {
2139 fmt.font_size = wp_get_font_size_index(
2140 font_size, DEFAULT_FONT_SIZE);
2141 fmt.cs.font_size = TRUE;
2143 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2145 gtk_widget_destroy (dialog);
2147 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2151 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2153 ModestMsgEditWindowPrivate *priv;
2155 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2156 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2158 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2160 update_dimmed (window);
2165 update_dimmed (ModestMsgEditWindow *window)
2167 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2168 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2172 gboolean editor_focused;
2174 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2175 editor_focused = gtk_widget_is_focus (priv->msg_body);
2177 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2178 gtk_action_set_sensitive (action, rich_text && editor_focused);
2179 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2180 gtk_action_set_sensitive (action, rich_text && editor_focused);
2181 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2182 gtk_action_set_sensitive (action, rich_text && editor_focused);
2183 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2184 gtk_action_set_sensitive (action, rich_text && editor_focused);
2185 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2186 gtk_action_set_sensitive (action, rich_text && editor_focused);
2187 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2188 gtk_action_set_sensitive (action, rich_text && editor_focused);
2189 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2190 gtk_action_set_sensitive (action, rich_text && editor_focused);
2191 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2192 gtk_action_set_sensitive (action, rich_text && editor_focused);
2193 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2194 gtk_action_set_sensitive (action, rich_text && editor_focused);
2195 widget = priv->font_color_button;
2196 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2197 widget = priv->font_size_toolitem;
2198 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2199 widget = priv->font_face_toolitem;
2200 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2204 setup_insensitive_handlers (ModestMsgEditWindow *window)
2206 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2207 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2210 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2211 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2212 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2213 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2215 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2216 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2217 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2218 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2219 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2220 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2221 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2222 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2223 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2224 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2225 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2226 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2227 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2228 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2229 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2230 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2231 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2232 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2233 widget = priv->font_color_button;
2234 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2235 widget = priv->font_size_toolitem;
2236 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2237 widget = priv->font_face_toolitem;
2238 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2243 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2245 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2248 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2249 gtk_action_set_sensitive (action, can_undo);
2253 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2256 GtkTextIter match_start, match_end;
2258 if (image_id == NULL)
2261 gtk_text_buffer_get_start_iter (buffer, &iter);
2263 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2264 GSList *tags = gtk_text_iter_get_tags (&match_start);
2266 for (node = tags; node != NULL; node = g_slist_next (node)) {
2267 GtkTextTag *tag = (GtkTextTag *) node->data;
2268 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2269 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2270 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2272 offset = gtk_text_iter_get_offset (&match_start);
2273 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2274 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2278 gtk_text_iter_forward_char (&iter);
2283 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2285 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2286 GtkTextIter real_start, real_end;
2287 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2289 if (gtk_text_iter_compare (start, end) > 0) {
2293 real_start = *start;
2297 GSList *tags = gtk_text_iter_get_tags (&real_start);
2299 for (node = tags; node != NULL; node = g_slist_next (node)) {
2300 GtkTextTag *tag = (GtkTextTag *) node->data;
2301 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2302 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2304 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2306 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2309 } while (gtk_text_iter_forward_char (&real_start)&&
2310 (gtk_text_iter_compare (&real_start, &real_end)<=0));
2314 msg_body_focus (GtkWidget *focus,
2315 GdkEventFocus *event,
2319 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2324 recpt_field_changed (GtkTextBuffer *buffer,
2325 ModestMsgEditWindow *editor)
2327 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2328 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2329 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2330 gboolean dim = FALSE;
2333 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2334 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2335 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2337 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2338 gtk_text_buffer_get_char_count (cc_buffer) +
2339 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2341 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2342 gtk_action_set_sensitive (action, !dim);
2343 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2344 gtk_action_set_sensitive (action, !dim);
2348 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2350 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2354 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2356 gboolean rich_text, editor_focused;
2358 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2359 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2360 editor_focused = gtk_widget_is_focus (priv->msg_body);
2363 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2364 else if (!editor_focused)
2365 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2369 reset_modified (ModestMsgEditWindow *editor)
2371 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2372 GtkTextBuffer *buffer;
2374 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2375 gtk_text_buffer_set_modified (buffer, FALSE);
2376 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2377 gtk_text_buffer_set_modified (buffer, FALSE);
2378 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2379 gtk_text_buffer_set_modified (buffer, FALSE);
2380 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2384 is_modified (ModestMsgEditWindow *editor)
2386 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2387 GtkTextBuffer *buffer;
2389 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2390 if (gtk_text_buffer_get_modified (buffer))
2392 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2393 if (gtk_text_buffer_get_modified (buffer))
2395 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2396 if (gtk_text_buffer_get_modified (buffer))
2398 if (gtk_text_buffer_get_modified (priv->text_buffer))
2405 modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
2407 ModestMsgEditWindowPrivate *priv = NULL;
2409 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2410 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2412 /* check if there's no recipient added */
2413 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2414 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2415 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2416 /* no recipient contents, then select contacts */
2417 modest_msg_edit_window_open_addressbook (window, NULL);
2421 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
2423 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
2425 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
2428 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2435 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2436 ModestMsgEditWindow *window)
2438 modest_msg_edit_window_attach_file (window);
2442 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2444 ModestMsgEditWindow *window)
2446 ModestWindowPrivate *parent_priv;
2451 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2452 selection = gtk_clipboard_wait_for_text (clipboard);
2453 focused = gtk_window_get_focus (GTK_WINDOW (window));
2455 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2456 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2457 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2458 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2462 update_window_title (ModestMsgEditWindow *window)
2464 ModestMsgEditWindowPrivate *priv = NULL;
2465 const gchar *subject;
2467 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2468 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2469 if (subject == NULL || subject[0] == '\0')
2470 subject = _("mail_va_new_email");
2472 gtk_window_set_title (GTK_WINDOW (window), subject);
2477 subject_field_changed (GtkEditable *editable,
2478 ModestMsgEditWindow *window)
2480 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2481 update_window_title (window);
2482 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2486 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2489 ModestMsgEditWindowPrivate *priv = NULL;
2491 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2492 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2494 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2496 gtk_widget_show_all (priv->find_toolbar);
2497 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2499 gtk_widget_hide_all (priv->find_toolbar);
2500 gtk_widget_grab_focus (priv->msg_body);
2506 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2507 ModestMsgEditWindow *window)
2509 gchar *current_search = NULL;
2510 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2512 GtkTextIter selection_start, selection_end;
2513 GtkTextIter match_start, match_end;
2515 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2516 if ((current_search == NULL) && (strcmp (current_search, "") == 0)) {
2517 g_free (current_search);
2521 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2522 result = gtk_text_iter_forward_search (&selection_end, current_search, GTK_TEXT_SEARCH_VISIBLE_ONLY, &match_start, &match_end, NULL);
2524 GtkTextIter buffer_start;
2525 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2526 result = gtk_text_iter_forward_search (&buffer_start, current_search, GTK_TEXT_SEARCH_VISIBLE_ONLY, &match_start, &match_end, &selection_start);
2529 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2530 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2532 /* TODO: warning about non succesful search */
2534 g_free (current_search);
2538 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2539 ModestMsgEditWindow *window)
2541 GtkToggleAction *toggle;
2542 ModestWindowPrivate *parent_priv;
2543 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2545 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2546 gtk_toggle_action_set_active (toggle, FALSE);