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 to_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 /* list my signals */
130 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
131 struct _ModestMsgEditWindowPrivate {
133 GtkWidget *header_box;
135 ModestPairList *from_field_protos;
136 GtkWidget *from_field;
140 GtkWidget *bcc_field;
141 GtkWidget *subject_field;
142 GtkWidget *attachments_view;
143 GtkWidget *priority_icon;
144 GtkWidget *add_attachment_button;
146 GtkWidget *cc_caption;
147 GtkWidget *bcc_caption;
148 GtkWidget *attachments_caption;
150 GtkTextBuffer *text_buffer;
152 GtkWidget *font_size_toolitem;
153 GtkWidget *font_face_toolitem;
154 GtkWidget *font_color_button;
155 GSList *font_items_group;
156 GtkWidget *font_tool_button_label;
157 GSList *size_items_group;
158 GtkWidget *size_tool_button_label;
165 TnyHeaderFlags priority_flags;
169 gulong clipboard_change_handler_id;
174 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
175 MODEST_TYPE_MSG_EDIT_WINDOW, \
176 ModestMsgEditWindowPrivate))
178 static GtkWindowClass *parent_class = NULL;
180 /* uncomment the following if you have defined any signals */
181 /* static guint signals[LAST_SIGNAL] = {0}; */
184 modest_msg_edit_window_get_type (void)
186 static GType my_type = 0;
188 static const GTypeInfo my_info = {
189 sizeof(ModestMsgEditWindowClass),
190 NULL, /* base init */
191 NULL, /* base finalize */
192 (GClassInitFunc) modest_msg_edit_window_class_init,
193 NULL, /* class finalize */
194 NULL, /* class data */
195 sizeof(ModestMsgEditWindow),
197 (GInstanceInitFunc) modest_msg_edit_window_init,
200 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
201 "ModestMsgEditWindow",
204 wp_text_buffer_library_init ();
210 save_state (ModestWindow *self)
212 modest_widget_memory_save (modest_runtime_get_conf(),
213 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
218 restore_settings (ModestMsgEditWindow *self)
220 modest_widget_memory_restore (modest_runtime_get_conf(),
221 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
226 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
228 GObjectClass *gobject_class;
229 ModestWindowClass *modest_window_class;
230 gobject_class = (GObjectClass*) klass;
231 modest_window_class = (ModestWindowClass*) klass;
233 parent_class = g_type_class_peek_parent (klass);
234 gobject_class->finalize = modest_msg_edit_window_finalize;
236 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
237 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
238 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
239 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
240 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
242 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
244 modest_window_class->save_state_func = save_state;
248 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
250 ModestMsgEditWindowPrivate *priv;
251 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
253 priv->msg_body = NULL;
254 priv->from_field = NULL;
255 priv->to_field = NULL;
256 priv->cc_field = NULL;
257 priv->bcc_field = NULL;
258 priv->subject_field = NULL;
259 priv->attachments = NULL;
261 priv->zoom_level = 1.0;
263 priv->cc_caption = NULL;
264 priv->bcc_caption = NULL;
266 priv->priority_flags = 0;
268 priv->draft_msg = NULL;
269 priv->clipboard_change_handler_id = 0;
273 /* FIXME: this is a dup from the one in gtk/ */
276 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
278 static ModestPairList*
279 get_transports (void)
281 GSList *transports = NULL;
283 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
284 GSList *accounts = modest_account_mgr_account_names (account_mgr,
285 TRUE /* only enabled accounts. */);
287 GSList *cursor = accounts;
289 const gchar *account_name = cursor->data;
290 gchar *from_string = NULL;
292 from_string = modest_account_mgr_get_from_string (account_mgr,
296 if (from_string && account_name) {
297 gchar *name = g_strdup (account_name);
298 ModestPair *pair = modest_pair_new ((gpointer) name,
299 (gpointer) from_string , TRUE);
300 transports = g_slist_prepend (transports, pair);
303 cursor = cursor->next;
305 g_slist_free (accounts);
311 init_window (ModestMsgEditWindow *obj)
313 GtkWidget *from_caption, *to_caption, *subject_caption;
314 GtkWidget *main_vbox;
315 ModestMsgEditWindowPrivate *priv;
317 GtkSizeGroup *size_group;
319 GtkWidget *scroll_area;
320 GtkWidget *subject_box;
321 GtkWidget *attachment_icon;
323 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
325 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
327 /* Note: This ModestPairList* must exist for as long as the combo
328 * that uses it, because the ModestComboBox uses the ID opaquely,
329 * so it can't know how to manage its memory. */
330 priv->from_field_protos = get_transports ();
332 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
334 priv->to_field = modest_recpt_editor_new ();
335 priv->cc_field = modest_recpt_editor_new ();
336 priv->bcc_field = modest_recpt_editor_new ();
337 subject_box = gtk_hbox_new (FALSE, 0);
338 priv->priority_icon = gtk_image_new ();
339 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
340 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
341 g_object_set (G_OBJECT (priv->subject_field), "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL);
342 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
343 priv->add_attachment_button = gtk_button_new ();
344 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
345 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
346 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
347 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
348 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
349 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
350 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
351 priv->attachments_view = modest_attachments_view_new (NULL);
353 priv->header_box = gtk_vbox_new (FALSE, 0);
355 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
356 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
357 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
358 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
359 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
360 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
361 g_object_unref (size_group);
363 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
364 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
365 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
366 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
367 gtk_size_group_add_widget (size_group, priv->subject_field);
368 gtk_size_group_add_widget (size_group, priv->attachments_view);
369 g_object_unref (size_group);
371 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
372 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
373 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
374 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
375 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
376 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
377 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
380 priv->msg_body = wp_text_view_new ();
381 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
382 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
383 g_object_set (priv->text_buffer, "font_scale", 1.0, NULL);
384 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
385 /* gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
386 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
388 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
389 G_CALLBACK (text_buffer_refresh_attributes), obj);
390 g_signal_connect (G_OBJECT (priv->text_buffer), "delete-range",
391 G_CALLBACK (text_buffer_delete_range), obj);
392 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
393 G_CALLBACK (text_buffer_can_undo), obj);
394 g_signal_connect (G_OBJECT (obj), "window-state-event",
395 G_CALLBACK (modest_msg_edit_window_window_state_event),
397 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
398 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
399 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
400 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
401 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
402 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
404 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
405 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
407 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
408 G_CALLBACK (msg_body_focus), obj);
409 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
410 G_CALLBACK (msg_body_focus), obj);
411 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
412 "changed", G_CALLBACK (to_field_changed), obj);
413 to_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
414 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
416 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
417 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
418 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
420 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
422 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
423 frame = gtk_frame_new (NULL);
424 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
426 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
427 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
428 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
430 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL)) {
431 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
432 gtk_widget_hide (priv->cc_caption);
434 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL)) {
435 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
436 gtk_widget_hide (priv->bcc_caption);
439 gtk_container_add (GTK_CONTAINER(obj), priv->scroll);
440 scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
441 gtk_container_add (GTK_CONTAINER (frame), scroll_area);
442 gtk_container_set_focus_vadjustment (GTK_CONTAINER (scroll_area),
443 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
445 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
446 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
452 modest_msg_edit_window_finalize (GObject *obj)
454 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
457 if (priv->clipboard_change_handler_id > 0) {
458 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), priv->clipboard_change_handler_id);
459 priv->clipboard_change_handler_id = 0;
462 /* This had to stay alive for as long as the combobox that used it: */
463 modest_pair_list_free (priv->from_field_protos);
465 G_OBJECT_CLASS(parent_class)->finalize (obj);
469 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMsgEditWindow *self)
471 GtkWidget *close_dialog;
472 ModestMsgEditWindowPrivate *priv;
475 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
476 modest_window_save_state (MODEST_WINDOW (self));
477 if (is_modified (self)) {
478 close_dialog = hildon_note_new_confirmation (GTK_WINDOW (self), _("mcen_nc_no_email_message_modified_save_changes"));
479 response = gtk_dialog_run (GTK_DIALOG (close_dialog));
480 gtk_widget_destroy (close_dialog);
482 if (response != GTK_RESPONSE_CANCEL) {
483 modest_ui_actions_on_save_to_drafts (NULL, self);
486 /* /\* remove old message from drafts *\/ */
487 /* if (priv->draft_msg) { */
488 /* TnyHeader *header = tny_msg_get_header (priv->draft_msg); */
489 /* TnyAccount *account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(), */
491 /* TNY_ACCOUNT_TYPE_STORE); */
492 /* TnyFolder *folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS); */
493 /* g_return_val_if_fail (TNY_IS_HEADER (header), FALSE); */
494 /* g_return_val_if_fail (TNY_IS_FOLDER (folder), FALSE); */
495 /* tny_folder_remove_msg (folder, header, NULL); */
496 /* g_object_unref (folder); */
497 /* g_object_unref (header); */
498 /* g_object_unref (priv->draft_msg); */
499 /* priv->draft_msg = NULL; */
501 gtk_widget_destroy (GTK_WIDGET (self));
507 menubar_to_menu (GtkUIManager *ui_manager)
509 GtkWidget *main_menu;
513 /* Create new main menu */
514 main_menu = gtk_menu_new();
516 /* Get the menubar from the UI manager */
517 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
519 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
523 menu = GTK_WIDGET (iter->data);
524 gtk_widget_reparent(menu, main_menu);
526 iter = g_list_next (iter);
533 set_msg (ModestMsgEditWindow *self, TnyMsg *msg)
536 const gchar *to, *cc, *bcc, *subject;
538 ModestMsgEditWindowPrivate *priv;
541 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
542 g_return_if_fail (TNY_IS_MSG (msg));
544 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
546 header = tny_msg_get_header (msg);
547 to = tny_header_get_to (header);
548 cc = tny_header_get_cc (header);
549 bcc = tny_header_get_bcc (header);
550 subject = tny_header_get_subject (header);
553 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
555 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
557 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
559 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
561 update_window_title (self);
563 /* gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
564 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
565 body = modest_tny_msg_get_body (msg, TRUE);
567 if ((body == NULL)||(body[0] == '\0')) {
569 body = modest_text_utils_convert_to_html ("");
571 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
572 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
575 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
578 /* Get the default format required from configuration */
579 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
580 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
583 /* Set the default focus depending on having already a To: field or not */
584 if ((!to)||(*to == '\0')) {
585 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
587 gtk_widget_grab_focus (priv->msg_body);
590 /* TODO: lower priority, select in the From: combo to the
591 value that comes from msg <- not sure, should it be
594 /* Add attachments to the view */
595 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
596 if (priv->attachments == NULL)
597 gtk_widget_hide_all (priv->attachments_caption);
599 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
600 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
602 reset_modified (self);
604 update_dimmed (self);
605 text_buffer_can_undo (priv->text_buffer, FALSE, self);
607 priv->draft_msg = msg;
611 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
614 GList *item_children, *node;
615 GtkWidget *bin_child;
617 bin_child = gtk_bin_get_child (GTK_BIN(item));
619 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
621 for (node = item_children; node != NULL; node = g_list_next (node)) {
622 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
623 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
626 g_list_free (item_children);
630 menu_tool_button_dont_expand (GtkMenuToolButton *item)
633 GList *item_children, *node;
635 box = gtk_bin_get_child (GTK_BIN (item));
636 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
637 item_children = gtk_container_get_children (GTK_CONTAINER (box));
639 for (node = item_children; node != NULL; node = g_list_next (node)) {
640 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
641 if (GTK_IS_TOGGLE_BUTTON (node->data))
642 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
643 else if (GTK_IS_BUTTON (node->data))
644 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
646 g_list_free (item_children);
651 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
653 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
654 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
655 GtkWidget *placeholder;
656 GtkWidget *tool_item;
661 GtkWidget *sizes_menu;
662 GtkWidget *fonts_menu;
663 GSList *radio_group = NULL;
668 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
669 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
671 /* should we hide the toolbar? */
672 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
673 gtk_widget_hide (parent_priv->toolbar);
675 /* Font color placeholder */
676 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
677 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
680 tool_item = GTK_WIDGET (gtk_tool_item_new ());
681 priv->font_color_button = hildon_color_button_new ();
682 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
683 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
684 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
685 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
686 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
687 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
688 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
690 /* Font size and face placeholder */
691 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
692 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
694 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
695 priv->size_tool_button_label = gtk_label_new (NULL);
696 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
697 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
698 size_text,"</span>", NULL);
699 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
701 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
702 sizes_menu = gtk_menu_new ();
703 priv->size_items_group = NULL;
705 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
706 GtkWidget *size_menu_item;
708 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
709 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
710 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
711 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
712 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
713 gtk_widget_show (size_menu_item);
715 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
719 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
720 GtkWidget *item = (GtkWidget *) node->data;
721 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
725 priv->size_items_group = g_slist_reverse (priv->size_items_group);
726 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
727 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
728 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
729 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
730 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
731 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
732 priv->font_size_toolitem = tool_item;
735 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
736 priv->font_tool_button_label = gtk_label_new (NULL);
737 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
738 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
740 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
741 fonts_menu = gtk_menu_new ();
742 priv->font_items_group = NULL;
744 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
745 GtkWidget *font_menu_item;
746 GtkWidget *child_label;
748 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
749 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
750 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
751 wp_get_font_name (font_index), "</span>", NULL);
752 gtk_label_set_markup (GTK_LABEL (child_label), markup);
755 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
756 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
757 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
758 gtk_widget_show (font_menu_item);
760 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
763 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
764 GtkWidget *item = (GtkWidget *) node->data;
765 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
768 priv->font_items_group = g_slist_reverse (priv->font_items_group);
769 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
770 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
771 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
772 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
773 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
774 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
775 priv->font_face_toolitem = tool_item;
777 /* Set expand and homogeneous for remaining items */
778 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
779 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
780 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
781 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
782 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
783 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
784 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
785 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
786 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
794 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name)
797 ModestWindowPrivate *parent_priv;
798 ModestMsgEditWindowPrivate *priv;
799 GtkActionGroup *action_group;
800 GError *error = NULL;
801 GdkPixbuf *window_icon = NULL;
804 gboolean prefer_formatted;
807 g_return_val_if_fail (msg, NULL);
809 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
811 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
812 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
814 parent_priv->ui_manager = gtk_ui_manager_new();
815 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
816 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
818 /* Add common actions */
819 gtk_action_group_add_actions (action_group,
820 modest_msg_edit_action_entries,
821 G_N_ELEMENTS (modest_msg_edit_action_entries),
823 gtk_action_group_add_toggle_actions (action_group,
824 modest_msg_edit_toggle_action_entries,
825 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
827 gtk_action_group_add_radio_actions (action_group,
828 modest_msg_edit_alignment_radio_action_entries,
829 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
831 G_CALLBACK (modest_ui_actions_on_change_justify),
833 gtk_action_group_add_radio_actions (action_group,
834 modest_msg_edit_zoom_action_entries,
835 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
837 G_CALLBACK (modest_ui_actions_on_change_zoom),
839 gtk_action_group_add_radio_actions (action_group,
840 modest_msg_edit_priority_action_entries,
841 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
843 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
845 gtk_action_group_add_radio_actions (action_group,
846 modest_msg_edit_file_format_action_entries,
847 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
848 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
849 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
851 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
852 g_object_unref (action_group);
854 /* Load the UI definition */
855 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml", &error);
857 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
858 g_clear_error (&error);
861 /* Add accelerators */
862 gtk_window_add_accel_group (GTK_WINDOW (obj),
863 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
866 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
867 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
870 init_window (MODEST_MSG_EDIT_WINDOW(obj));
872 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
874 gtk_window_set_icon_from_file (GTK_WINDOW(obj), MODEST_APP_ICON, NULL);
876 g_signal_connect (G_OBJECT(obj), "delete-event",
877 G_CALLBACK(on_delete_event), obj);
879 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
881 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
883 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
885 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg);
887 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
889 /* Set window icon */
890 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
891 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
893 /* Dim at start clipboard actions */
894 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
895 gtk_action_set_sensitive (action, FALSE);
896 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
897 gtk_action_set_sensitive (action, FALSE);
899 /* set initial state of cc and bcc */
900 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
901 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
902 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
903 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
904 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
905 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
907 /* Setup the file format */
908 conf = modest_runtime_get_conf ();
909 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
911 g_clear_error (&error);
912 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
914 file_format = (prefer_formatted) ?
915 MODEST_FILE_FORMAT_FORMATTED_TEXT :
916 MODEST_FILE_FORMAT_PLAIN_TEXT;
917 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
919 return (ModestWindow*) obj;
923 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
925 GString **string_buffer = (GString **) user_data;
927 *string_buffer = g_string_append (*string_buffer, buffer);
933 * @result: A new string which should be freed with g_free().
936 get_formatted_data (ModestMsgEditWindow *edit_window)
938 ModestMsgEditWindowPrivate *priv;
939 GString *string_buffer = g_string_new ("");
941 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
943 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
945 return g_string_free (string_buffer, FALSE);
950 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
953 const gchar *account_name;
954 ModestMsgEditWindowPrivate *priv;
956 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
958 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
960 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
961 g_return_val_if_fail (account_name, NULL);
964 /* don't free these (except from) */
965 data = g_slice_new0 (MsgData);
966 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
968 data->account_name = g_strdup (account_name);
969 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
970 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
971 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
972 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
973 if (priv->draft_msg) {
974 data->draft_msg = g_object_ref (priv->draft_msg);
976 data->draft_msg = NULL;
979 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
981 gtk_text_buffer_get_bounds (buf, &b, &e);
982 data->plain_body = g_strdup (gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE)); /* returns a copy */
984 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
985 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
987 data->html_body = NULL;
989 data->attachments = priv->attachments; /* TODO: copy and free ? */
990 data->priority_flags = priv->priority_flags;
995 /* TODO: We must duplicate this implementation for GNOME and Maemo, but that is unwise. */
997 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1000 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1008 g_free (data->subject);
1009 g_free (data->plain_body);
1010 g_free (data->html_body);
1011 if (data->draft_msg != NULL) {
1012 g_object_unref (data->draft_msg);
1013 data->draft_msg = NULL;
1015 g_free (data->account_name);
1017 /* TODO: Free data->attachments? */
1019 g_slice_free (MsgData, data);
1023 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1026 ModestMsgEditWindowPrivate *priv = NULL;
1027 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1029 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1031 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1033 return MODEST_MSG_EDIT_FORMAT_HTML;
1035 return MODEST_MSG_EDIT_FORMAT_TEXT;
1039 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1040 ModestMsgEditFormat format)
1042 ModestMsgEditWindowPrivate *priv;
1044 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1045 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1048 case MODEST_MSG_EDIT_FORMAT_HTML:
1049 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1051 case MODEST_MSG_EDIT_FORMAT_TEXT:
1052 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1055 g_return_if_reached ();
1059 ModestMsgEditFormatState *
1060 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1062 ModestMsgEditFormatState *format_state = NULL;
1063 ModestMsgEditWindowPrivate *priv;
1064 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1066 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1067 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1069 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1071 format_state = g_new0 (ModestMsgEditFormatState, 1);
1072 format_state->bold = buffer_format->bold&0x1;
1073 format_state->italics = buffer_format->italic&0x1;
1074 format_state->bullet = buffer_format->bullet&0x1;
1075 format_state->color = buffer_format->color;
1076 format_state->font_size = buffer_format->font_size;
1077 format_state->font_family = wp_get_font_name (buffer_format->font);
1078 format_state->justification = buffer_format->justification;
1079 g_free (buffer_format);
1081 return format_state;
1086 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1087 const ModestMsgEditFormatState *format_state)
1089 ModestMsgEditWindowPrivate *priv;
1090 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1091 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1092 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1093 g_return_if_fail (format_state != NULL);
1095 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1096 gtk_widget_grab_focus (priv->msg_body);
1097 buffer_format->bold = (format_state->bold != FALSE);
1098 buffer_format->italic = (format_state->italics != FALSE);
1099 buffer_format->color = format_state->color;
1100 buffer_format->font_size = format_state->font_size;
1101 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1102 buffer_format->justification = format_state->justification;
1103 buffer_format->bullet = format_state->bullet;
1105 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1107 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1108 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1109 buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
1110 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1111 buffer_format->cs.font = (buffer_format->font != current_format->font);
1112 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1113 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1115 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1116 if (buffer_format->cs.bold) {
1117 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1119 if (buffer_format->cs.italic) {
1120 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1122 if (buffer_format->cs.color) {
1123 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1125 if (buffer_format->cs.font_size) {
1126 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->font_size));
1128 if (buffer_format->cs.justification) {
1129 switch (buffer_format->justification) {
1130 case GTK_JUSTIFY_LEFT:
1131 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1133 case GTK_JUSTIFY_CENTER:
1134 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1136 case GTK_JUSTIFY_RIGHT:
1137 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1144 if (buffer_format->cs.font) {
1145 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->font));
1147 if (buffer_format->cs.bullet) {
1148 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) (buffer_format->bullet));
1150 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1151 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1153 g_free (current_format);
1158 toggle_action_set_active_block_notify (GtkToggleAction *action,
1161 GSList *proxies = NULL;
1163 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1164 proxies != NULL; proxies = g_slist_next (proxies)) {
1165 GtkWidget *widget = (GtkWidget *) proxies->data;
1166 gtk_action_block_activate_from (GTK_ACTION (action), widget);
1169 gtk_toggle_action_set_active (action, value);
1171 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1172 proxies != NULL; proxies = g_slist_next (proxies)) {
1173 GtkWidget *widget = (GtkWidget *) proxies->data;
1174 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
1179 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1181 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1183 ModestWindowPrivate *parent_priv;
1184 ModestMsgEditWindowPrivate *priv;
1185 GtkWidget *new_size_menuitem;
1186 GtkWidget *new_font_menuitem;
1188 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1189 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1191 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1192 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1193 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1194 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1196 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1197 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1198 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1201 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1203 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1204 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1206 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1207 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1209 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1210 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1212 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1213 G_CALLBACK (modest_msg_edit_window_color_button_change),
1215 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1216 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1217 G_CALLBACK (modest_msg_edit_window_color_button_change),
1220 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1221 buffer_format->font_size))->data);
1222 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1226 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1227 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1228 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1230 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1231 G_CALLBACK (modest_msg_edit_window_size_change),
1233 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1234 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1235 G_CALLBACK (modest_msg_edit_window_size_change),
1239 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1240 buffer_format->font))->data);
1241 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1245 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1246 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1247 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1249 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1250 G_CALLBACK (modest_msg_edit_window_font_change),
1252 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1253 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1254 G_CALLBACK (modest_msg_edit_window_font_change),
1258 g_free (buffer_format);
1264 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1267 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1268 ModestMsgEditWindowPrivate *priv;
1269 GtkWidget *dialog = NULL;
1271 const GdkColor *new_color = NULL;
1273 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1274 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1276 #ifdef MODEST_HILDON_VERSION_0
1277 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1278 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1280 dialog = hildon_color_chooser_new ();
1281 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1282 #endif /*MODEST_HILDON_VERSION_0*/
1283 g_free (buffer_format);
1285 response = gtk_dialog_run (GTK_DIALOG (dialog));
1287 case GTK_RESPONSE_OK: {
1288 #ifdef MODEST_HILDON_VERSION_0
1289 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1292 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1294 #endif /*MODEST_HILDON_VERSION_0*/
1301 gtk_widget_destroy (dialog);
1303 if (new_color != NULL)
1304 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1309 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1312 ModestMsgEditWindowPrivate *priv;
1313 GtkWidget *dialog = NULL;
1315 GdkColor *old_color = NULL;
1316 const GdkColor *new_color = NULL;
1318 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1319 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1321 #ifdef MODEST_HILDON_VERSION_0
1322 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1323 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1325 dialog = hildon_color_chooser_new ();
1326 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1327 #endif /*MODEST_HILDON_VERSION_9*/
1329 response = gtk_dialog_run (GTK_DIALOG (dialog));
1331 case GTK_RESPONSE_OK: {
1332 #ifdef MODEST_HILDON_VERSION_0
1333 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1336 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1338 #endif /*MODEST_HILDON_VERSION_0*/
1344 gtk_widget_destroy (dialog);
1346 if (new_color != NULL)
1347 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1352 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1355 ModestMsgEditWindowPrivate *priv;
1356 GtkWidget *dialog = NULL;
1358 gchar *filename = NULL;
1360 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1362 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1364 response = gtk_dialog_run (GTK_DIALOG (dialog));
1366 case GTK_RESPONSE_OK:
1367 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1372 gtk_widget_destroy (dialog);
1375 GdkPixbuf *pixbuf = NULL;
1376 GtkTextIter position;
1377 GtkTextMark *insert_mark;
1379 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
1382 GdkPixbufFormat *pixbuf_format;
1384 image_file_id = g_open (filename, O_RDONLY, 0);
1385 pixbuf_format = gdk_pixbuf_get_file_info (filename, NULL, NULL);
1386 if ((image_file_id != -1)&&(pixbuf_format != NULL)) {
1387 TnyMimePart *image_part;
1388 TnyStream *image_stream;
1394 mime_types = gdk_pixbuf_format_get_mime_types (pixbuf_format);
1395 if ((mime_types != NULL) && (mime_types[0] != NULL)) {
1396 mime_type = mime_types[0];
1398 mime_type = "image/unknown";
1400 image_part = tny_platform_factory_new_mime_part
1401 (modest_runtime_get_platform_factory ());
1402 image_stream = TNY_STREAM (tny_fs_stream_new (image_file_id));
1404 tny_mime_part_construct_from_stream (image_part, image_stream, mime_type);
1405 g_strfreev (mime_types);
1407 content_id = g_strdup_printf ("%d", priv->last_cid);
1408 tny_mime_part_set_content_id (image_part, content_id);
1409 g_free (content_id);
1412 basename = g_path_get_basename (filename);
1413 tny_mime_part_set_filename (image_part, basename);
1416 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1417 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1418 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (image_part)), pixbuf);
1419 priv->attachments = g_list_prepend (priv->attachments, image_part);
1420 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1422 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1423 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1424 gtk_widget_show_all (priv->attachments_caption);
1425 } else if (image_file_id == -1) {
1426 close (image_file_id);
1435 modest_msg_edit_window_attach_file (ModestMsgEditWindow *window)
1438 ModestMsgEditWindowPrivate *priv;
1439 GtkWidget *dialog = NULL;
1441 gchar *uri = NULL, *filename = NULL;
1443 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1445 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1447 response = gtk_dialog_run (GTK_DIALOG (dialog));
1449 case GTK_RESPONSE_OK:
1450 uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
1451 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1456 gtk_widget_destroy (dialog);
1460 GnomeVFSHandle *handle = NULL;
1461 GnomeVFSResult result;
1463 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1464 if (result == GNOME_VFS_OK) {
1465 TnyMimePart *mime_part;
1467 const gchar *mime_type = NULL;
1470 GnomeVFSFileInfo info;
1472 if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE) == GNOME_VFS_OK)
1473 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1474 mime_part = tny_platform_factory_new_mime_part
1475 (modest_runtime_get_platform_factory ());
1476 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1478 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1480 content_id = g_strdup_printf ("%d", priv->last_cid);
1481 tny_mime_part_set_content_id (mime_part, content_id);
1482 g_free (content_id);
1485 basename = g_path_get_basename (filename);
1486 tny_mime_part_set_filename (mime_part, basename);
1489 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1490 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1492 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1493 gtk_widget_show_all (priv->attachments_caption);
1494 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1501 modest_msg_edit_window_attach_file_noninteractive (
1502 ModestMsgEditWindow *window,
1506 ModestMsgEditWindowPrivate *priv;
1508 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1513 file_id = g_open (filename, O_RDONLY, 0);
1514 if (file_id != -1) {
1515 TnyMimePart *mime_part;
1517 const gchar *mime_type;
1521 mime_type = gnome_vfs_get_file_mime_type_fast (filename, NULL);
1522 mime_part = tny_platform_factory_new_mime_part
1523 (modest_runtime_get_platform_factory ());
1524 stream = TNY_STREAM (tny_fs_stream_new (file_id));
1526 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1528 content_id = g_strdup_printf ("%d", priv->last_cid);
1529 tny_mime_part_set_content_id (mime_part, content_id);
1530 g_free (content_id);
1533 basename = g_path_get_basename (filename);
1534 tny_mime_part_set_filename (mime_part, basename);
1537 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1538 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1540 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1541 gtk_widget_show_all (priv->attachments_caption);
1542 } else if (file_id == -1) {
1549 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1552 ModestMsgEditWindowPrivate *priv;
1553 gboolean clean_list = FALSE;
1555 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1556 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1558 if (att_list == NULL) {
1559 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1563 if (att_list == NULL) {
1564 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1566 GtkWidget *confirmation_dialog = NULL;
1567 gboolean dialog_response;
1569 if (att_list->next == NULL) {
1570 gchar *message = g_strdup_printf (_("emev_nc_delete_attachment"),
1571 tny_mime_part_get_filename (TNY_MIME_PART (att_list->data)));
1572 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1575 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), _("emev_nc_delete_attachments"));
1577 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1578 gtk_widget_destroy (confirmation_dialog);
1579 if (!dialog_response) {
1581 g_list_free (att_list);
1584 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1586 for (node = att_list; node != NULL; node = g_list_next (node)) {
1587 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1588 const gchar *att_id;
1589 priv->attachments = g_list_remove (priv->attachments, mime_part);
1591 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1593 att_id = tny_mime_part_get_content_id (mime_part);
1595 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1597 g_object_unref (mime_part);
1598 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1603 g_list_free (att_list);
1607 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1610 ModestMsgEditWindowPrivate *priv;
1611 GdkColor *new_color;
1612 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1614 #ifdef MODEST_HILDON_VERSION_0
1615 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1618 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1620 #endif /*MODEST_HILDON_VERSION_0*/
1622 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1624 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1629 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1632 ModestMsgEditWindowPrivate *priv;
1633 gint new_size_index;
1634 ModestMsgEditWindow *window;
1637 window = MODEST_MSG_EDIT_WINDOW (userdata);
1638 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1639 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1641 if (gtk_check_menu_item_get_active (menu_item)) {
1643 WPTextBufferFormat format;
1645 memset (&format, 0, sizeof (format));
1646 wp_text_buffer_get_current_state (WP_TEXT_BUFFER (priv->text_buffer), &format);
1648 label = gtk_bin_get_child (GTK_BIN (menu_item));
1650 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1651 format.cs.font_size = TRUE;
1652 format.cs.text_position = TRUE;
1653 format.cs.font = TRUE;
1654 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1655 wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format);
1657 /* if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, */
1658 /* (gpointer) wp_get_font_size_index (new_size_index, 12))) */
1659 /* wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body)); */
1661 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1662 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1663 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1669 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1672 ModestMsgEditWindowPrivate *priv;
1673 gint new_font_index;
1674 ModestMsgEditWindow *window;
1677 window = MODEST_MSG_EDIT_WINDOW (userdata);
1678 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1679 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1681 if (gtk_check_menu_item_get_active (menu_item)) {
1684 label = gtk_bin_get_child (GTK_BIN (menu_item));
1686 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1688 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1689 (gpointer) new_font_index))
1690 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1692 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1693 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1694 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1700 modest_msg_edit_window_set_zoom (ModestWindow *window,
1703 ModestMsgEditWindowPrivate *priv;
1705 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1707 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1708 priv->zoom_level = zoom;
1709 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom);
1713 modest_msg_edit_window_get_zoom (ModestWindow *window)
1715 ModestMsgEditWindowPrivate *priv;
1717 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1719 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1720 return priv->zoom_level;
1724 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1726 ModestWindowPrivate *parent_priv;
1727 GtkRadioAction *zoom_radio_action;
1728 GSList *group, *node;
1730 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1731 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1732 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1734 group = gtk_radio_action_get_group (zoom_radio_action);
1736 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1737 hildon_banner_show_information (NULL, NULL, _("mcen_ib_max_zoom_level"));
1741 for (node = group; node != NULL; node = g_slist_next (node)) {
1742 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1743 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1751 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1753 ModestWindowPrivate *parent_priv;
1754 GtkRadioAction *zoom_radio_action;
1755 GSList *group, *node;
1757 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1758 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1759 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1761 group = gtk_radio_action_get_group (zoom_radio_action);
1763 for (node = group; node != NULL; node = g_slist_next (node)) {
1764 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1765 if (node->next != NULL) {
1766 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1769 hildon_banner_show_information (NULL, NULL, _("mcen_ib_min_zoom_level"));
1777 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1779 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1780 ModestWindowPrivate *parent_priv;
1781 ModestWindowMgr *mgr;
1782 gboolean is_fullscreen;
1783 GtkAction *fs_toggle_action;
1786 mgr = modest_runtime_get_window_mgr ();
1787 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1789 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1791 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1792 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1793 if (is_fullscreen != active)
1794 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1802 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
1804 ModestWindowPrivate *parent_priv;
1805 GtkAction *fs_toggle_action;
1808 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1810 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1811 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
1812 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
1816 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
1819 ModestMsgEditWindowPrivate *priv = NULL;
1820 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1822 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1823 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1825 gtk_widget_show (priv->cc_caption);
1827 gtk_widget_hide (priv->cc_caption);
1828 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
1832 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
1835 ModestMsgEditWindowPrivate *priv = NULL;
1836 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1838 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1839 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1841 gtk_widget_show (priv->bcc_caption);
1843 gtk_widget_hide (priv->bcc_caption);
1844 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
1848 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
1849 ModestRecptEditor *editor)
1851 ModestMsgEditWindowPrivate *priv;
1853 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1854 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
1855 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1857 if (editor == NULL) {
1858 GtkWidget *view_focus;
1859 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
1861 /* This code should be kept in sync with ModestRecptEditor. The
1862 textview inside the recpt editor is the one that really gets the
1863 focus. As it's inside a scrolled window, and this one inside the
1864 hbox recpt editor inherits from, we'll need to go up in the
1865 hierarchy to know if the text view is part of the recpt editor
1866 or if it's a different text entry */
1868 if (gtk_widget_get_parent (view_focus)) {
1869 GtkWidget *first_parent;
1871 first_parent = gtk_widget_get_parent (view_focus);
1872 if (gtk_widget_get_parent (first_parent) &&
1873 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
1874 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
1879 editor = MODEST_RECPT_EDITOR (priv->to_field);
1883 modest_address_book_select_addresses (editor);
1888 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
1890 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1892 modest_msg_edit_window_open_addressbook (window, NULL);
1896 modest_msg_edit_window_show_toolbar (ModestWindow *self,
1897 gboolean show_toolbar)
1899 ModestWindowPrivate *parent_priv;
1901 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1902 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1904 /* FIXME: we can not just use the code of
1905 modest_msg_edit_window_setup_toolbar because it has a
1906 mixture of both initialization and creation code. */
1909 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1911 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1915 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
1916 TnyHeaderFlags priority_flags)
1918 ModestMsgEditWindowPrivate *priv;
1920 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1922 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1923 priority_flags = priority_flags & (TNY_HEADER_FLAG_HIGH_PRIORITY);
1925 if (priv->priority_flags != priority_flags) {
1927 priv->priority_flags = priority_flags;
1929 switch (priority_flags) {
1930 case TNY_HEADER_FLAG_HIGH_PRIORITY:
1931 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
1932 gtk_widget_show (priv->priority_icon);
1934 case TNY_HEADER_FLAG_LOW_PRIORITY:
1935 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
1936 gtk_widget_show (priv->priority_icon);
1939 gtk_widget_hide (priv->priority_icon);
1946 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
1949 ModestMsgEditWindowPrivate *priv;
1950 gint current_format;
1952 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1954 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1956 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
1957 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
1959 if (current_format != file_format) {
1960 switch (file_format) {
1961 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
1962 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1964 case MODEST_FILE_FORMAT_PLAIN_TEXT:
1968 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
1969 response = gtk_dialog_run (GTK_DIALOG (dialog));
1970 gtk_widget_destroy (dialog);
1971 if (response == GTK_RESPONSE_OK)
1972 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1976 update_dimmed (window);
1981 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
1984 ModestMsgEditWindowPrivate *priv;
1985 WPTextBufferFormat oldfmt, fmt;
1986 gint old_position = 0;
1990 GdkColor *color = NULL;
1991 gboolean bold, bold_set, italic, italic_set;
1992 gboolean underline, underline_set;
1993 gboolean strikethrough, strikethrough_set;
1994 gboolean position_set;
1995 gboolean font_size_set, font_set, color_set;
1998 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1999 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2001 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2003 /* First we get the currently selected font information */
2004 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2005 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2007 switch (oldfmt.text_position) {
2008 case TEXT_POSITION_NORMAL:
2011 case TEXT_POSITION_SUPERSCRIPT:
2019 g_object_set (G_OBJECT (dialog),
2020 "bold", oldfmt.bold != FALSE,
2021 "bold-set", !oldfmt.cs.bold,
2022 "underline", oldfmt.underline != FALSE,
2023 "underline-set", !oldfmt.cs.underline,
2024 "italic", oldfmt.italic != FALSE,
2025 "italic-set", !oldfmt.cs.italic,
2026 "strikethrough", oldfmt.strikethrough != FALSE,
2027 "strikethrough-set", !oldfmt.cs.strikethrough,
2028 "color", &oldfmt.color,
2029 "color-set", !oldfmt.cs.color,
2030 "size", wp_font_size[oldfmt.font_size],
2031 "size-set", !oldfmt.cs.font_size,
2032 "position", old_position,
2033 "position-set", !oldfmt.cs.text_position,
2034 "family", wp_get_font_name (oldfmt.font),
2035 "family-set", !oldfmt.cs.font,
2038 gtk_widget_show_all (dialog);
2039 response = gtk_dialog_run (GTK_DIALOG (dialog));
2040 if (response == GTK_RESPONSE_OK) {
2042 g_object_get( dialog,
2044 "bold-set", &bold_set,
2045 "underline", &underline,
2046 "underline-set", &underline_set,
2048 "italic-set", &italic_set,
2049 "strikethrough", &strikethrough,
2050 "strikethrough-set", &strikethrough_set,
2052 "color-set", &color_set,
2054 "size-set", &font_size_set,
2055 "family", &font_name,
2056 "family-set", &font_set,
2057 "position", &position,
2058 "position-set", &position_set,
2063 if (response == GTK_RESPONSE_OK) {
2064 memset(&fmt, 0, sizeof(fmt));
2070 fmt.italic = italic;
2071 fmt.cs.italic = TRUE;
2073 if (underline_set) {
2074 fmt.underline = underline;
2075 fmt.cs.underline = TRUE;
2077 if (strikethrough_set) {
2078 fmt.strikethrough = strikethrough;
2079 fmt.cs.strikethrough = TRUE;
2084 ? TEXT_POSITION_NORMAL
2085 : ( ( position == 1 )
2086 ? TEXT_POSITION_SUPERSCRIPT
2087 : TEXT_POSITION_SUBSCRIPT );
2088 fmt.cs.text_position = TRUE;
2092 fmt.cs.color = TRUE;
2095 fmt.font = wp_get_font_index(font_name,
2100 if (font_size_set) {
2101 fmt.font_size = wp_get_font_size_index(
2102 font_size, DEFAULT_FONT_SIZE);
2103 fmt.cs.font_size = TRUE;
2105 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2107 gtk_widget_destroy (dialog);
2109 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2113 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2115 ModestMsgEditWindowPrivate *priv;
2117 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2118 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2120 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2122 update_dimmed (window);
2127 update_dimmed (ModestMsgEditWindow *window)
2129 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2130 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2134 gboolean editor_focused;
2136 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2137 editor_focused = gtk_widget_is_focus (priv->msg_body);
2139 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2140 gtk_action_set_sensitive (action, rich_text && editor_focused);
2141 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2142 gtk_action_set_sensitive (action, rich_text && editor_focused);
2143 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2144 gtk_action_set_sensitive (action, rich_text && editor_focused);
2145 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2146 gtk_action_set_sensitive (action, rich_text && editor_focused);
2147 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2148 gtk_action_set_sensitive (action, rich_text && editor_focused);
2149 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2150 gtk_action_set_sensitive (action, rich_text && editor_focused);
2151 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2152 gtk_action_set_sensitive (action, rich_text && editor_focused);
2153 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2154 gtk_action_set_sensitive (action, rich_text && editor_focused);
2155 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2156 gtk_action_set_sensitive (action, rich_text && editor_focused);
2157 widget = priv->font_color_button;
2158 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2159 widget = priv->font_size_toolitem;
2160 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2161 widget = priv->font_face_toolitem;
2162 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2166 setup_insensitive_handlers (ModestMsgEditWindow *window)
2168 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2169 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2172 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2173 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2174 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2175 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2177 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2178 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2179 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2180 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2181 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2182 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2183 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2184 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2185 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2186 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2187 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2188 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2189 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2190 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2191 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2192 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2193 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2194 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2195 widget = priv->font_color_button;
2196 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2197 widget = priv->font_size_toolitem;
2198 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2199 widget = priv->font_face_toolitem;
2200 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2205 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2207 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2210 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2211 gtk_action_set_sensitive (action, can_undo);
2215 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2218 GtkTextIter match_start, match_end;
2220 if (image_id == NULL)
2223 gtk_text_buffer_get_start_iter (buffer, &iter);
2225 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2226 GSList *tags = gtk_text_iter_get_tags (&match_start);
2228 for (node = tags; node != NULL; node = g_slist_next (node)) {
2229 GtkTextTag *tag = (GtkTextTag *) node->data;
2230 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2231 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2232 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2234 offset = gtk_text_iter_get_offset (&match_start);
2235 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2236 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2240 gtk_text_iter_forward_char (&iter);
2245 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2247 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2248 GtkTextIter real_start, real_end;
2249 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2251 if (gtk_text_iter_compare (start, end) > 0) {
2255 real_start = *start;
2259 GSList *tags = gtk_text_iter_get_tags (&real_start);
2261 for (node = tags; node != NULL; node = g_slist_next (node)) {
2262 GtkTextTag *tag = (GtkTextTag *) node->data;
2263 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2264 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2266 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2268 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2271 } while (gtk_text_iter_forward_char (&real_start)&&
2272 (gtk_text_iter_compare (&real_start, &real_end)<=0));
2276 msg_body_focus (GtkWidget *focus,
2277 GdkEventFocus *event,
2281 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2286 to_field_changed (GtkTextBuffer *buffer,
2287 ModestMsgEditWindow *editor)
2289 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2292 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2293 gtk_action_set_sensitive (action, gtk_text_buffer_get_char_count (buffer) != 0);
2294 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2295 gtk_action_set_sensitive (action, gtk_text_buffer_get_char_count (buffer) != 0);
2299 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2301 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2305 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2307 gboolean rich_text, editor_focused;
2309 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2310 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2311 editor_focused = gtk_widget_is_focus (priv->msg_body);
2314 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2315 else if (!editor_focused)
2316 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2320 reset_modified (ModestMsgEditWindow *editor)
2322 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2323 GtkTextBuffer *buffer;
2325 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2326 gtk_text_buffer_set_modified (buffer, FALSE);
2327 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2328 gtk_text_buffer_set_modified (buffer, FALSE);
2329 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2330 gtk_text_buffer_set_modified (buffer, FALSE);
2331 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2335 is_modified (ModestMsgEditWindow *editor)
2337 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2338 GtkTextBuffer *buffer;
2340 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2341 if (gtk_text_buffer_get_modified (buffer))
2343 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2344 if (gtk_text_buffer_get_modified (buffer))
2346 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2347 if (gtk_text_buffer_get_modified (buffer))
2349 if (gtk_text_buffer_get_modified (priv->text_buffer))
2356 modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
2358 ModestMsgEditWindowPrivate *priv = NULL;
2360 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2361 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2363 /* check if there's no recipient added */
2364 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2365 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2366 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2367 /* no recipient contents, then select contacts */
2368 modest_msg_edit_window_open_addressbook (window, NULL);
2372 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
2374 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
2376 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
2379 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2386 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2387 ModestMsgEditWindow *window)
2389 modest_msg_edit_window_attach_file (window);
2393 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2395 ModestMsgEditWindow *window)
2397 ModestWindowPrivate *parent_priv;
2402 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2403 selection = gtk_clipboard_wait_for_text (clipboard);
2404 focused = gtk_window_get_focus (GTK_WINDOW (window));
2406 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2407 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2408 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2409 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2413 update_window_title (ModestMsgEditWindow *window)
2415 ModestMsgEditWindowPrivate *priv = NULL;
2416 const gchar *subject;
2418 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2419 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2420 if (subject == NULL || subject[0] == '\0')
2421 subject = _("mail_va_new_email");
2423 gtk_window_set_title (GTK_WINDOW (window), subject);
2428 subject_field_changed (GtkEditable *editable,
2429 ModestMsgEditWindow *window)
2431 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2432 update_window_title (window);
2433 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);