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 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 = 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); /* only free the accounts, not the elements,
316 * because they are used in the pairlist */
322 init_window (ModestMsgEditWindow *obj)
324 GtkWidget *from_caption, *to_caption, *subject_caption;
325 GtkWidget *main_vbox;
326 ModestMsgEditWindowPrivate *priv;
328 GtkSizeGroup *size_group;
330 GtkWidget *scroll_area;
331 GtkWidget *subject_box;
332 GtkWidget *attachment_icon;
333 GtkWidget *window_box;
335 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
337 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
339 /* Note: This ModestPairList* must exist for as long as the combo
340 * that uses it, because the ModestComboBox uses the ID opaquely,
341 * so it can't know how to manage its memory. */
342 priv->from_field_protos = get_transports ();
344 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
346 priv->to_field = modest_recpt_editor_new ();
347 priv->cc_field = modest_recpt_editor_new ();
348 priv->bcc_field = modest_recpt_editor_new ();
349 subject_box = gtk_hbox_new (FALSE, 0);
350 priv->priority_icon = gtk_image_new ();
351 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
352 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
353 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
354 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
355 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
356 priv->add_attachment_button = gtk_button_new ();
357 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
358 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
359 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
360 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
361 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
362 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
363 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
364 priv->attachments_view = modest_attachments_view_new (NULL);
366 priv->header_box = gtk_vbox_new (FALSE, 0);
368 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
369 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
370 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
371 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
372 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
373 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
374 g_object_unref (size_group);
376 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
377 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
378 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
379 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
380 gtk_size_group_add_widget (size_group, priv->subject_field);
381 gtk_size_group_add_widget (size_group, priv->attachments_view);
382 g_object_unref (size_group);
384 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
385 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
386 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
387 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
388 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
389 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
390 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
393 priv->msg_body = wp_text_view_new ();
394 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
395 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
396 g_object_set (priv->text_buffer, "font_scale", 1.0, NULL);
397 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
398 /* gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
399 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
401 priv->find_toolbar = hildon_find_toolbar_new (NULL);
402 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
404 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
405 G_CALLBACK (text_buffer_refresh_attributes), obj);
406 g_signal_connect (G_OBJECT (priv->text_buffer), "delete-range",
407 G_CALLBACK (text_buffer_delete_range), obj);
408 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
409 G_CALLBACK (text_buffer_can_undo), obj);
410 g_signal_connect (G_OBJECT (obj), "window-state-event",
411 G_CALLBACK (modest_msg_edit_window_window_state_event),
413 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
414 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
415 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
416 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
417 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
418 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
420 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
421 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
423 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
424 G_CALLBACK (msg_body_focus), obj);
425 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
426 G_CALLBACK (msg_body_focus), obj);
427 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
428 "changed", G_CALLBACK (recpt_field_changed), obj);
429 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
430 "changed", G_CALLBACK (recpt_field_changed), obj);
431 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
432 "changed", G_CALLBACK (recpt_field_changed), obj);
433 recpt_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
434 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
436 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
437 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
439 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
440 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
441 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
443 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
445 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
446 frame = gtk_frame_new (NULL);
447 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
449 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
450 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
451 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
453 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL)) {
454 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
455 gtk_widget_hide (priv->cc_caption);
457 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL)) {
458 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
459 gtk_widget_hide (priv->bcc_caption);
462 window_box = gtk_vbox_new (FALSE, 0);
463 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
464 gtk_box_pack_end (GTK_BOX (window_box), priv->find_toolbar, FALSE, FALSE, 0);
465 gtk_container_add (GTK_CONTAINER(obj), window_box);
466 scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
467 gtk_container_add (GTK_CONTAINER (frame), scroll_area);
468 gtk_container_set_focus_vadjustment (GTK_CONTAINER (scroll_area),
469 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
471 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
472 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
478 modest_msg_edit_window_finalize (GObject *obj)
480 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
482 if (priv->clipboard_change_handler_id > 0) {
483 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), priv->clipboard_change_handler_id);
484 priv->clipboard_change_handler_id = 0;
487 /* This had to stay alive for as long as the combobox that used it: */
488 modest_pair_list_free (priv->from_field_protos);
490 G_OBJECT_CLASS(parent_class)->finalize (obj);
494 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMsgEditWindow *self)
496 GtkWidget *close_dialog;
497 ModestMsgEditWindowPrivate *priv;
500 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
501 modest_window_save_state (MODEST_WINDOW (self));
502 if (is_modified (self)) {
503 close_dialog = hildon_note_new_confirmation (GTK_WINDOW (self), _("mcen_nc_no_email_message_modified_save_changes"));
504 response = gtk_dialog_run (GTK_DIALOG (close_dialog));
505 gtk_widget_destroy (close_dialog);
507 if (response != GTK_RESPONSE_CANCEL) {
508 modest_ui_actions_on_save_to_drafts (NULL, self);
511 /* /\* remove old message from drafts *\/ */
512 /* if (priv->draft_msg) { */
513 /* TnyHeader *header = tny_msg_get_header (priv->draft_msg); */
514 /* TnyAccount *account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(), */
516 /* TNY_ACCOUNT_TYPE_STORE); */
517 /* TnyFolder *folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS); */
518 /* g_return_val_if_fail (TNY_IS_HEADER (header), FALSE); */
519 /* g_return_val_if_fail (TNY_IS_FOLDER (folder), FALSE); */
520 /* tny_folder_remove_msg (folder, header, NULL); */
521 /* g_object_unref (folder); */
522 /* g_object_unref (header); */
523 /* g_object_unref (priv->draft_msg); */
524 /* priv->draft_msg = NULL; */
526 gtk_widget_destroy (GTK_WIDGET (self));
532 menubar_to_menu (GtkUIManager *ui_manager)
534 GtkWidget *main_menu;
538 /* Create new main menu */
539 main_menu = gtk_menu_new();
541 /* Get the menubar from the UI manager */
542 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
544 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
548 menu = GTK_WIDGET (iter->data);
549 gtk_widget_reparent(menu, main_menu);
551 iter = g_list_next (iter);
558 set_msg (ModestMsgEditWindow *self, TnyMsg *msg)
561 const gchar *to, *cc, *bcc, *subject;
563 ModestMsgEditWindowPrivate *priv;
565 TnyHeaderFlags priority_flags;
567 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
568 g_return_if_fail (TNY_IS_MSG (msg));
570 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
572 header = tny_msg_get_header (msg);
573 to = tny_header_get_to (header);
574 cc = tny_header_get_cc (header);
575 bcc = tny_header_get_bcc (header);
576 subject = tny_header_get_subject (header);
577 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
580 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
582 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
584 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
586 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
587 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
590 update_window_title (self);
592 /* gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
593 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
594 body = modest_tny_msg_get_body (msg, TRUE);
596 if ((body == NULL)||(body[0] == '\0')) {
598 body = modest_text_utils_convert_to_html ("");
600 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
601 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
604 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
607 /* Get the default format required from configuration */
608 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
609 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
612 /* Set the default focus depending on having already a To: field or not */
613 if ((!to)||(*to == '\0')) {
614 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
616 gtk_widget_grab_focus (priv->msg_body);
619 /* TODO: lower priority, select in the From: combo to the
620 value that comes from msg <- not sure, should it be
623 /* Add attachments to the view */
624 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
625 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
626 if (priv->attachments == NULL) {
627 gtk_widget_hide (priv->attachments_caption);
629 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
630 gtk_widget_show_all (priv->attachments_caption);
633 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
634 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
636 reset_modified (self);
638 update_dimmed (self);
639 text_buffer_can_undo (priv->text_buffer, FALSE, self);
641 priv->draft_msg = msg;
645 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
648 GList *item_children, *node;
649 GtkWidget *bin_child;
651 bin_child = gtk_bin_get_child (GTK_BIN(item));
653 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
655 for (node = item_children; node != NULL; node = g_list_next (node)) {
656 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
657 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
660 g_list_free (item_children);
664 menu_tool_button_dont_expand (GtkMenuToolButton *item)
667 GList *item_children, *node;
669 box = gtk_bin_get_child (GTK_BIN (item));
670 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
671 item_children = gtk_container_get_children (GTK_CONTAINER (box));
673 for (node = item_children; node != NULL; node = g_list_next (node)) {
674 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
675 if (GTK_IS_TOGGLE_BUTTON (node->data))
676 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
677 else if (GTK_IS_BUTTON (node->data))
678 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
680 g_list_free (item_children);
685 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
687 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
688 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
689 GtkWidget *placeholder;
690 GtkWidget *tool_item;
695 GtkWidget *sizes_menu;
696 GtkWidget *fonts_menu;
697 GSList *radio_group = NULL;
702 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
703 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
705 /* should we hide the toolbar? */
706 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
707 gtk_widget_hide (parent_priv->toolbar);
709 /* Font color placeholder */
710 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
711 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
714 tool_item = GTK_WIDGET (gtk_tool_item_new ());
715 priv->font_color_button = hildon_color_button_new ();
716 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
717 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
718 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
719 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
720 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
721 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
722 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
724 /* Font size and face placeholder */
725 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
726 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
728 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
729 priv->size_tool_button_label = gtk_label_new (NULL);
730 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
731 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
732 size_text,"</span>", NULL);
733 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
735 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
736 sizes_menu = gtk_menu_new ();
737 priv->size_items_group = NULL;
739 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
740 GtkWidget *size_menu_item;
742 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
743 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
744 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
745 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
746 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
747 gtk_widget_show (size_menu_item);
749 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
753 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
754 GtkWidget *item = (GtkWidget *) node->data;
755 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
759 priv->size_items_group = g_slist_reverse (priv->size_items_group);
760 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
761 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
762 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
763 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
764 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
765 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
766 priv->font_size_toolitem = tool_item;
769 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
770 priv->font_tool_button_label = gtk_label_new (NULL);
771 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
772 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
774 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
775 fonts_menu = gtk_menu_new ();
776 priv->font_items_group = NULL;
778 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
779 GtkWidget *font_menu_item;
780 GtkWidget *child_label;
782 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
783 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
784 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
785 wp_get_font_name (font_index), "</span>", NULL);
786 gtk_label_set_markup (GTK_LABEL (child_label), markup);
789 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
790 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
791 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
792 gtk_widget_show (font_menu_item);
794 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
797 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
798 GtkWidget *item = (GtkWidget *) node->data;
799 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
802 priv->font_items_group = g_slist_reverse (priv->font_items_group);
803 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
804 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
805 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
806 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
807 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
808 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
809 priv->font_face_toolitem = tool_item;
811 /* Set expand and homogeneous for remaining items */
812 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
813 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
814 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
815 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
816 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
817 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
818 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
819 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
820 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
828 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name)
831 ModestWindowPrivate *parent_priv;
832 ModestMsgEditWindowPrivate *priv;
833 GtkActionGroup *action_group;
834 GError *error = NULL;
835 GdkPixbuf *window_icon = NULL;
838 gboolean prefer_formatted;
840 ModestPair *account_pair = NULL;
842 g_return_val_if_fail (msg, NULL);
843 g_return_val_if_fail (account_name, NULL);
845 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
847 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
848 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
850 parent_priv->ui_manager = gtk_ui_manager_new();
851 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
852 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
854 /* Add common actions */
855 gtk_action_group_add_actions (action_group,
856 modest_msg_edit_action_entries,
857 G_N_ELEMENTS (modest_msg_edit_action_entries),
859 gtk_action_group_add_toggle_actions (action_group,
860 modest_msg_edit_toggle_action_entries,
861 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
863 gtk_action_group_add_radio_actions (action_group,
864 modest_msg_edit_alignment_radio_action_entries,
865 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
867 G_CALLBACK (modest_ui_actions_on_change_justify),
869 gtk_action_group_add_radio_actions (action_group,
870 modest_msg_edit_zoom_action_entries,
871 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
873 G_CALLBACK (modest_ui_actions_on_change_zoom),
875 gtk_action_group_add_radio_actions (action_group,
876 modest_msg_edit_priority_action_entries,
877 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
879 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
881 gtk_action_group_add_radio_actions (action_group,
882 modest_msg_edit_file_format_action_entries,
883 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
884 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
885 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
887 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
888 g_object_unref (action_group);
890 /* Load the UI definition */
891 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
894 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
895 g_clear_error (&error);
898 /* Add accelerators */
899 gtk_window_add_accel_group (GTK_WINDOW (obj),
900 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
903 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
904 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
907 init_window (MODEST_MSG_EDIT_WINDOW(obj));
909 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
911 gtk_window_set_icon_from_file (GTK_WINDOW(obj), MODEST_APP_ICON, NULL);
913 g_signal_connect (G_OBJECT(obj), "delete-event",
914 G_CALLBACK(on_delete_event), obj);
916 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
918 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
920 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
922 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
923 if (account_pair != NULL)
924 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
926 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg);
928 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
930 /* Set window icon */
931 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
932 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
934 /* Dim at start clipboard actions */
935 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
936 gtk_action_set_sensitive (action, FALSE);
937 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
938 gtk_action_set_sensitive (action, FALSE);
940 /* set initial state of cc and bcc */
941 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
942 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
943 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
944 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
945 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
946 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
948 /* Setup the file format */
949 conf = modest_runtime_get_conf ();
950 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
952 g_clear_error (&error);
953 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
955 file_format = (prefer_formatted) ?
956 MODEST_FILE_FORMAT_FORMATTED_TEXT :
957 MODEST_FILE_FORMAT_PLAIN_TEXT;
958 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
960 return (ModestWindow*) obj;
964 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
966 GString **string_buffer = (GString **) user_data;
968 *string_buffer = g_string_append (*string_buffer, buffer);
974 * @result: A new string which should be freed with g_free().
977 get_formatted_data (ModestMsgEditWindow *edit_window)
979 ModestMsgEditWindowPrivate *priv;
980 GString *string_buffer = g_string_new ("");
982 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
984 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
986 return g_string_free (string_buffer, FALSE);
991 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
994 const gchar *account_name;
995 ModestMsgEditWindowPrivate *priv;
997 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
999 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1001 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1002 g_return_val_if_fail (account_name, NULL);
1005 /* don't free these (except from) */
1006 data = g_slice_new0 (MsgData);
1007 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1009 data->account_name = g_strdup (account_name);
1010 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1011 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1012 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1013 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1014 if (priv->draft_msg) {
1015 data->draft_msg = g_object_ref (priv->draft_msg);
1017 data->draft_msg = NULL;
1020 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1022 gtk_text_buffer_get_bounds (buf, &b, &e);
1023 data->plain_body = g_strdup (gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE)); /* returns a copy */
1025 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1026 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1028 data->html_body = NULL;
1030 data->attachments = priv->attachments; /* TODO: copy and free ? */
1031 data->priority_flags = priv->priority_flags;
1036 /* TODO: We must duplicate this implementation for GNOME and Maemo, but that is unwise. */
1038 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1041 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1049 g_free (data->subject);
1050 g_free (data->plain_body);
1051 g_free (data->html_body);
1052 if (data->draft_msg != NULL) {
1053 g_object_unref (data->draft_msg);
1054 data->draft_msg = NULL;
1056 g_free (data->account_name);
1058 /* TODO: Free data->attachments? */
1060 g_slice_free (MsgData, data);
1064 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1067 ModestMsgEditWindowPrivate *priv = NULL;
1068 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1070 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1072 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1074 return MODEST_MSG_EDIT_FORMAT_HTML;
1076 return MODEST_MSG_EDIT_FORMAT_TEXT;
1080 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1081 ModestMsgEditFormat format)
1083 ModestMsgEditWindowPrivate *priv;
1085 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1086 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1089 case MODEST_MSG_EDIT_FORMAT_HTML:
1090 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1092 case MODEST_MSG_EDIT_FORMAT_TEXT:
1093 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1096 g_return_if_reached ();
1100 ModestMsgEditFormatState *
1101 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1103 ModestMsgEditFormatState *format_state = NULL;
1104 ModestMsgEditWindowPrivate *priv;
1105 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1107 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1108 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1110 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1112 format_state = g_new0 (ModestMsgEditFormatState, 1);
1113 format_state->bold = buffer_format->bold&0x1;
1114 format_state->italics = buffer_format->italic&0x1;
1115 format_state->bullet = buffer_format->bullet&0x1;
1116 format_state->color = buffer_format->color;
1117 format_state->font_size = buffer_format->font_size;
1118 format_state->font_family = wp_get_font_name (buffer_format->font);
1119 format_state->justification = buffer_format->justification;
1120 g_free (buffer_format);
1122 return format_state;
1127 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1128 const ModestMsgEditFormatState *format_state)
1130 ModestMsgEditWindowPrivate *priv;
1131 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1132 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1133 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1134 g_return_if_fail (format_state != NULL);
1136 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1137 gtk_widget_grab_focus (priv->msg_body);
1138 buffer_format->bold = (format_state->bold != FALSE);
1139 buffer_format->italic = (format_state->italics != FALSE);
1140 buffer_format->color = format_state->color;
1141 buffer_format->font_size = format_state->font_size;
1142 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1143 buffer_format->justification = format_state->justification;
1144 buffer_format->bullet = format_state->bullet;
1146 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1148 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1149 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1150 buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
1151 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1152 buffer_format->cs.font = (buffer_format->font != current_format->font);
1153 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1154 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1156 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1157 if (buffer_format->cs.bold) {
1158 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1160 if (buffer_format->cs.italic) {
1161 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1163 if (buffer_format->cs.color) {
1164 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1166 if (buffer_format->cs.font_size) {
1167 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->font_size));
1169 if (buffer_format->cs.justification) {
1170 switch (buffer_format->justification) {
1171 case GTK_JUSTIFY_LEFT:
1172 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1174 case GTK_JUSTIFY_CENTER:
1175 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1177 case GTK_JUSTIFY_RIGHT:
1178 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1185 if (buffer_format->cs.font) {
1186 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->font));
1188 if (buffer_format->cs.bullet) {
1189 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((int)buffer_format->bullet));
1191 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1192 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1194 g_free (current_format);
1199 toggle_action_set_active_block_notify (GtkToggleAction *action,
1202 GSList *proxies = NULL;
1204 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1205 proxies != NULL; proxies = g_slist_next (proxies)) {
1206 GtkWidget *widget = (GtkWidget *) proxies->data;
1207 gtk_action_block_activate_from (GTK_ACTION (action), widget);
1210 gtk_toggle_action_set_active (action, value);
1212 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1213 proxies != NULL; proxies = g_slist_next (proxies)) {
1214 GtkWidget *widget = (GtkWidget *) proxies->data;
1215 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
1220 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1222 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1224 ModestWindowPrivate *parent_priv;
1225 ModestMsgEditWindowPrivate *priv;
1226 GtkWidget *new_size_menuitem;
1227 GtkWidget *new_font_menuitem;
1229 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1230 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1232 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1233 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1234 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1235 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1237 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1238 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1239 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1242 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1244 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1245 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1247 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1248 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1250 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1251 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1253 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1254 G_CALLBACK (modest_msg_edit_window_color_button_change),
1256 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1257 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1258 G_CALLBACK (modest_msg_edit_window_color_button_change),
1261 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1262 buffer_format->font_size))->data);
1263 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1267 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1268 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1269 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1271 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1272 G_CALLBACK (modest_msg_edit_window_size_change),
1274 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1275 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1276 G_CALLBACK (modest_msg_edit_window_size_change),
1280 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1281 buffer_format->font))->data);
1282 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1286 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1287 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1288 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1290 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1291 G_CALLBACK (modest_msg_edit_window_font_change),
1293 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1294 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1295 G_CALLBACK (modest_msg_edit_window_font_change),
1299 g_free (buffer_format);
1305 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1308 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1309 ModestMsgEditWindowPrivate *priv;
1310 GtkWidget *dialog = NULL;
1312 const GdkColor *new_color = NULL;
1314 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1315 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1317 #ifdef MODEST_HILDON_VERSION_0
1318 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1319 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1321 dialog = hildon_color_chooser_new ();
1322 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1323 #endif /*MODEST_HILDON_VERSION_0*/
1324 g_free (buffer_format);
1326 response = gtk_dialog_run (GTK_DIALOG (dialog));
1328 case GTK_RESPONSE_OK: {
1329 #ifdef MODEST_HILDON_VERSION_0
1330 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1333 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1335 #endif /*MODEST_HILDON_VERSION_0*/
1342 gtk_widget_destroy (dialog);
1344 if (new_color != NULL)
1345 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1350 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1353 ModestMsgEditWindowPrivate *priv;
1354 GtkWidget *dialog = NULL;
1356 GdkColor *old_color = NULL;
1357 const GdkColor *new_color = NULL;
1359 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1360 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1362 #ifdef MODEST_HILDON_VERSION_0
1363 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1364 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1366 dialog = hildon_color_chooser_new ();
1367 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1368 #endif /*MODEST_HILDON_VERSION_9*/
1370 response = gtk_dialog_run (GTK_DIALOG (dialog));
1372 case GTK_RESPONSE_OK: {
1373 #ifdef MODEST_HILDON_VERSION_0
1374 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1377 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1379 #endif /*MODEST_HILDON_VERSION_0*/
1385 gtk_widget_destroy (dialog);
1387 if (new_color != NULL)
1388 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1393 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1396 ModestMsgEditWindowPrivate *priv;
1397 GtkWidget *dialog = NULL;
1399 gchar *filename = NULL;
1401 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1403 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1405 response = gtk_dialog_run (GTK_DIALOG (dialog));
1407 case GTK_RESPONSE_OK:
1408 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1413 gtk_widget_destroy (dialog);
1416 GdkPixbuf *pixbuf = NULL;
1417 GtkTextIter position;
1418 GtkTextMark *insert_mark;
1420 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
1423 GdkPixbufFormat *pixbuf_format;
1425 image_file_id = g_open (filename, O_RDONLY, 0);
1426 pixbuf_format = gdk_pixbuf_get_file_info (filename, NULL, NULL);
1427 if ((image_file_id != -1)&&(pixbuf_format != NULL)) {
1428 TnyMimePart *image_part;
1429 TnyStream *image_stream;
1435 mime_types = gdk_pixbuf_format_get_mime_types (pixbuf_format);
1436 if ((mime_types != NULL) && (mime_types[0] != NULL)) {
1437 mime_type = mime_types[0];
1439 mime_type = "image/unknown";
1441 image_part = tny_platform_factory_new_mime_part
1442 (modest_runtime_get_platform_factory ());
1443 image_stream = TNY_STREAM (tny_fs_stream_new (image_file_id));
1445 tny_mime_part_construct_from_stream (image_part, image_stream, mime_type);
1446 g_strfreev (mime_types);
1448 content_id = g_strdup_printf ("%d", priv->last_cid);
1449 tny_mime_part_set_content_id (image_part, content_id);
1450 g_free (content_id);
1453 basename = g_path_get_basename (filename);
1454 tny_mime_part_set_filename (image_part, basename);
1457 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1458 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1459 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (image_part)), pixbuf);
1460 priv->attachments = g_list_prepend (priv->attachments, image_part);
1461 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1463 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1464 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1465 gtk_widget_show_all (priv->attachments_caption);
1466 } else if (image_file_id == -1) {
1467 close (image_file_id);
1476 modest_msg_edit_window_attach_file (ModestMsgEditWindow *window)
1479 ModestMsgEditWindowPrivate *priv;
1480 GtkWidget *dialog = NULL;
1482 gchar *uri = NULL, *filename = NULL;
1484 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1486 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1488 response = gtk_dialog_run (GTK_DIALOG (dialog));
1490 case GTK_RESPONSE_OK:
1491 uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
1492 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1497 gtk_widget_destroy (dialog);
1501 GnomeVFSHandle *handle = NULL;
1502 GnomeVFSResult result;
1504 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1505 if (result == GNOME_VFS_OK) {
1506 TnyMimePart *mime_part;
1508 const gchar *mime_type = NULL;
1511 GnomeVFSFileInfo info;
1513 if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE) == GNOME_VFS_OK)
1514 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1515 mime_part = tny_platform_factory_new_mime_part
1516 (modest_runtime_get_platform_factory ());
1517 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1519 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1521 content_id = g_strdup_printf ("%d", priv->last_cid);
1522 tny_mime_part_set_content_id (mime_part, content_id);
1523 g_free (content_id);
1526 basename = g_path_get_basename (filename);
1527 tny_mime_part_set_filename (mime_part, basename);
1530 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1531 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1533 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1534 gtk_widget_show_all (priv->attachments_caption);
1535 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1542 modest_msg_edit_window_attach_file_noninteractive (
1543 ModestMsgEditWindow *window,
1544 const gchar *file_uri)
1547 ModestMsgEditWindowPrivate *priv;
1549 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1554 /* TODO: We should probably try to use only the URI,
1555 * instead of using a filename.
1557 gchar* filename = g_filename_from_uri (file_uri, NULL, NULL);
1559 g_warning("%s: g_filename_from_uri(%s) failed.\n", __FUNCTION__, file_uri);
1562 file_id = g_open (filename, O_RDONLY, 0);
1563 if (file_id != -1) {
1564 TnyMimePart *mime_part;
1566 const gchar *mime_type;
1570 mime_type = gnome_vfs_get_file_mime_type_fast (filename, NULL);
1571 mime_part = tny_platform_factory_new_mime_part
1572 (modest_runtime_get_platform_factory ());
1573 stream = TNY_STREAM (tny_fs_stream_new (file_id));
1575 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1577 content_id = g_strdup_printf ("%d", priv->last_cid);
1578 tny_mime_part_set_content_id (mime_part, content_id);
1579 g_free (content_id);
1582 basename = g_path_get_basename (filename);
1583 tny_mime_part_set_filename (mime_part, basename);
1586 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1587 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1589 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1590 gtk_widget_show_all (priv->attachments_caption);
1591 } else if (file_id == -1) {
1593 g_warning("file to be attached does not exist: %s", filename);
1601 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1604 ModestMsgEditWindowPrivate *priv;
1605 gboolean clean_list = FALSE;
1607 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1608 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1610 if (att_list == NULL) {
1611 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1615 if (att_list == NULL) {
1616 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1618 GtkWidget *confirmation_dialog = NULL;
1619 gboolean dialog_response;
1621 gchar *message = NULL;
1622 const gchar *filename = NULL;
1624 if (att_list->next == NULL) {
1625 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1629 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1630 att_list->next == NULL), filename);
1631 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1633 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1634 gtk_widget_destroy (confirmation_dialog);
1635 if (!dialog_response) {
1637 g_list_free (att_list);
1640 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1642 for (node = att_list; node != NULL; node = g_list_next (node)) {
1643 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1644 const gchar *att_id;
1645 priv->attachments = g_list_remove (priv->attachments, mime_part);
1647 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1649 if (priv->attachments == NULL)
1650 gtk_widget_hide (priv->attachments_caption);
1651 att_id = tny_mime_part_get_content_id (mime_part);
1653 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1655 g_object_unref (mime_part);
1656 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1661 g_list_free (att_list);
1665 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1668 ModestMsgEditWindowPrivate *priv;
1669 GdkColor *new_color;
1670 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1672 #ifdef MODEST_HILDON_VERSION_0
1673 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1676 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1678 #endif /*MODEST_HILDON_VERSION_0*/
1680 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1682 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1687 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1690 ModestMsgEditWindowPrivate *priv;
1691 gint new_size_index;
1692 ModestMsgEditWindow *window;
1695 window = MODEST_MSG_EDIT_WINDOW (userdata);
1696 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1697 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1699 if (gtk_check_menu_item_get_active (menu_item)) {
1701 WPTextBufferFormat format;
1703 memset (&format, 0, sizeof (format));
1704 wp_text_buffer_get_current_state (WP_TEXT_BUFFER (priv->text_buffer), &format);
1706 label = gtk_bin_get_child (GTK_BIN (menu_item));
1708 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1709 format.cs.font_size = TRUE;
1710 format.cs.text_position = TRUE;
1711 format.cs.font = TRUE;
1712 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1713 wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format);
1715 /* if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, */
1716 /* (gpointer) wp_get_font_size_index (new_size_index, 12))) */
1717 /* wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body)); */
1719 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1720 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1721 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1727 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1730 ModestMsgEditWindowPrivate *priv;
1731 gint new_font_index;
1732 ModestMsgEditWindow *window;
1735 window = MODEST_MSG_EDIT_WINDOW (userdata);
1736 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1737 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1739 if (gtk_check_menu_item_get_active (menu_item)) {
1742 label = gtk_bin_get_child (GTK_BIN (menu_item));
1744 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1746 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1747 (gpointer) new_font_index))
1748 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1750 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1751 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1752 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1758 modest_msg_edit_window_set_zoom (ModestWindow *window,
1761 ModestMsgEditWindowPrivate *priv;
1763 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1765 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1766 priv->zoom_level = zoom;
1767 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom);
1771 modest_msg_edit_window_get_zoom (ModestWindow *window)
1773 ModestMsgEditWindowPrivate *priv;
1775 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1777 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1778 return priv->zoom_level;
1782 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1784 ModestWindowPrivate *parent_priv;
1785 GtkRadioAction *zoom_radio_action;
1786 GSList *group, *node;
1788 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1789 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1790 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1792 group = gtk_radio_action_get_group (zoom_radio_action);
1794 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1795 hildon_banner_show_information (NULL, NULL, _("mcen_ib_max_zoom_level"));
1799 for (node = group; node != NULL; node = g_slist_next (node)) {
1800 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1801 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1809 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1811 ModestWindowPrivate *parent_priv;
1812 GtkRadioAction *zoom_radio_action;
1813 GSList *group, *node;
1815 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1816 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1817 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1819 group = gtk_radio_action_get_group (zoom_radio_action);
1821 for (node = group; node != NULL; node = g_slist_next (node)) {
1822 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1823 if (node->next != NULL) {
1824 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1827 hildon_banner_show_information (NULL, NULL, _("mcen_ib_min_zoom_level"));
1835 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1837 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1838 ModestWindowPrivate *parent_priv;
1839 ModestWindowMgr *mgr;
1840 gboolean is_fullscreen;
1841 GtkAction *fs_toggle_action;
1844 mgr = modest_runtime_get_window_mgr ();
1845 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1847 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1849 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1850 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1851 if (is_fullscreen != active)
1852 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1860 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
1862 ModestWindowPrivate *parent_priv;
1863 GtkAction *fs_toggle_action;
1866 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1868 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1869 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
1870 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
1874 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
1877 ModestMsgEditWindowPrivate *priv = NULL;
1878 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1880 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1881 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1883 gtk_widget_show (priv->cc_caption);
1885 gtk_widget_hide (priv->cc_caption);
1886 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
1890 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
1893 ModestMsgEditWindowPrivate *priv = NULL;
1894 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1896 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1897 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1899 gtk_widget_show (priv->bcc_caption);
1901 gtk_widget_hide (priv->bcc_caption);
1902 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
1906 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
1907 ModestRecptEditor *editor)
1909 ModestMsgEditWindowPrivate *priv;
1911 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1912 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
1913 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1915 if (editor == NULL) {
1916 GtkWidget *view_focus;
1917 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
1919 /* This code should be kept in sync with ModestRecptEditor. The
1920 textview inside the recpt editor is the one that really gets the
1921 focus. As it's inside a scrolled window, and this one inside the
1922 hbox recpt editor inherits from, we'll need to go up in the
1923 hierarchy to know if the text view is part of the recpt editor
1924 or if it's a different text entry */
1926 if (gtk_widget_get_parent (view_focus)) {
1927 GtkWidget *first_parent;
1929 first_parent = gtk_widget_get_parent (view_focus);
1930 if (gtk_widget_get_parent (first_parent) &&
1931 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
1932 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
1937 editor = MODEST_RECPT_EDITOR (priv->to_field);
1941 modest_address_book_select_addresses (editor);
1946 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
1948 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1950 modest_msg_edit_window_open_addressbook (window, NULL);
1954 modest_msg_edit_window_show_toolbar (ModestWindow *self,
1955 gboolean show_toolbar)
1957 ModestWindowPrivate *parent_priv;
1959 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1960 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1962 /* FIXME: we can not just use the code of
1963 modest_msg_edit_window_setup_toolbar because it has a
1964 mixture of both initialization and creation code. */
1967 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1969 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1973 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
1974 TnyHeaderFlags priority_flags)
1976 ModestMsgEditWindowPrivate *priv;
1977 ModestWindowPrivate *parent_priv;
1979 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1981 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1982 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1983 priority_flags = priority_flags & (TNY_HEADER_FLAG_HIGH_PRIORITY);
1985 if (priv->priority_flags != priority_flags) {
1986 GtkAction *priority_action = NULL;
1988 priv->priority_flags = priority_flags;
1990 switch (priority_flags) {
1991 case TNY_HEADER_FLAG_HIGH_PRIORITY:
1992 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
1993 gtk_widget_show (priv->priority_icon);
1994 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1995 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
1997 case TNY_HEADER_FLAG_LOW_PRIORITY:
1998 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
1999 gtk_widget_show (priv->priority_icon);
2000 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2001 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2004 gtk_widget_hide (priv->priority_icon);
2005 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2006 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2009 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2010 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2015 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2018 ModestMsgEditWindowPrivate *priv;
2019 gint current_format;
2021 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2023 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2025 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2026 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2028 if (current_format != file_format) {
2029 switch (file_format) {
2030 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2031 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2033 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2037 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2038 response = gtk_dialog_run (GTK_DIALOG (dialog));
2039 gtk_widget_destroy (dialog);
2040 if (response == GTK_RESPONSE_OK)
2041 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2045 update_dimmed (window);
2050 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2053 ModestMsgEditWindowPrivate *priv;
2054 WPTextBufferFormat oldfmt, fmt;
2055 gint old_position = 0;
2059 GdkColor *color = NULL;
2060 gboolean bold, bold_set, italic, italic_set;
2061 gboolean underline, underline_set;
2062 gboolean strikethrough, strikethrough_set;
2063 gboolean position_set;
2064 gboolean font_size_set, font_set, color_set;
2067 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2068 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2070 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2072 /* First we get the currently selected font information */
2073 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2074 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2076 switch (oldfmt.text_position) {
2077 case TEXT_POSITION_NORMAL:
2080 case TEXT_POSITION_SUPERSCRIPT:
2088 g_object_set (G_OBJECT (dialog),
2089 "bold", oldfmt.bold != FALSE,
2090 "bold-set", !oldfmt.cs.bold,
2091 "underline", oldfmt.underline != FALSE,
2092 "underline-set", !oldfmt.cs.underline,
2093 "italic", oldfmt.italic != FALSE,
2094 "italic-set", !oldfmt.cs.italic,
2095 "strikethrough", oldfmt.strikethrough != FALSE,
2096 "strikethrough-set", !oldfmt.cs.strikethrough,
2097 "color", &oldfmt.color,
2098 "color-set", !oldfmt.cs.color,
2099 "size", wp_font_size[oldfmt.font_size],
2100 "size-set", !oldfmt.cs.font_size,
2101 "position", old_position,
2102 "position-set", !oldfmt.cs.text_position,
2103 "family", wp_get_font_name (oldfmt.font),
2104 "family-set", !oldfmt.cs.font,
2107 gtk_widget_show_all (dialog);
2108 response = gtk_dialog_run (GTK_DIALOG (dialog));
2109 if (response == GTK_RESPONSE_OK) {
2111 g_object_get( dialog,
2113 "bold-set", &bold_set,
2114 "underline", &underline,
2115 "underline-set", &underline_set,
2117 "italic-set", &italic_set,
2118 "strikethrough", &strikethrough,
2119 "strikethrough-set", &strikethrough_set,
2121 "color-set", &color_set,
2123 "size-set", &font_size_set,
2124 "family", &font_name,
2125 "family-set", &font_set,
2126 "position", &position,
2127 "position-set", &position_set,
2132 if (response == GTK_RESPONSE_OK) {
2133 memset(&fmt, 0, sizeof(fmt));
2139 fmt.italic = italic;
2140 fmt.cs.italic = TRUE;
2142 if (underline_set) {
2143 fmt.underline = underline;
2144 fmt.cs.underline = TRUE;
2146 if (strikethrough_set) {
2147 fmt.strikethrough = strikethrough;
2148 fmt.cs.strikethrough = TRUE;
2153 ? TEXT_POSITION_NORMAL
2154 : ( ( position == 1 )
2155 ? TEXT_POSITION_SUPERSCRIPT
2156 : TEXT_POSITION_SUBSCRIPT );
2157 fmt.cs.text_position = TRUE;
2161 fmt.cs.color = TRUE;
2164 fmt.font = wp_get_font_index(font_name,
2169 if (font_size_set) {
2170 fmt.font_size = wp_get_font_size_index(
2171 font_size, DEFAULT_FONT_SIZE);
2172 fmt.cs.font_size = TRUE;
2174 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2176 gtk_widget_destroy (dialog);
2178 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2182 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2184 ModestMsgEditWindowPrivate *priv;
2186 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2187 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2189 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2191 update_dimmed (window);
2196 update_dimmed (ModestMsgEditWindow *window)
2198 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2199 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2203 gboolean editor_focused;
2205 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2206 editor_focused = gtk_widget_is_focus (priv->msg_body);
2208 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2209 gtk_action_set_sensitive (action, rich_text && editor_focused);
2210 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2211 gtk_action_set_sensitive (action, rich_text && editor_focused);
2212 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2213 gtk_action_set_sensitive (action, rich_text && editor_focused);
2214 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2215 gtk_action_set_sensitive (action, rich_text && editor_focused);
2216 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2217 gtk_action_set_sensitive (action, rich_text && editor_focused);
2218 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2219 gtk_action_set_sensitive (action, rich_text && editor_focused);
2220 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2221 gtk_action_set_sensitive (action, rich_text && editor_focused);
2222 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2223 gtk_action_set_sensitive (action, rich_text && editor_focused);
2224 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2225 gtk_action_set_sensitive (action, rich_text && editor_focused);
2226 widget = priv->font_color_button;
2227 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2228 widget = priv->font_size_toolitem;
2229 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2230 widget = priv->font_face_toolitem;
2231 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2235 setup_insensitive_handlers (ModestMsgEditWindow *window)
2237 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2238 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2241 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2242 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2243 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2244 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2246 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2247 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2248 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2249 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2250 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2251 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2252 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2253 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2254 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2255 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2256 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2257 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2258 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2259 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2260 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2261 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2262 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2263 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2264 widget = priv->font_color_button;
2265 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2266 widget = priv->font_size_toolitem;
2267 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2268 widget = priv->font_face_toolitem;
2269 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2274 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2276 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2279 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2280 gtk_action_set_sensitive (action, can_undo);
2284 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2287 GtkTextIter match_start, match_end;
2289 if (image_id == NULL)
2292 gtk_text_buffer_get_start_iter (buffer, &iter);
2294 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2295 GSList *tags = gtk_text_iter_get_tags (&match_start);
2297 for (node = tags; node != NULL; node = g_slist_next (node)) {
2298 GtkTextTag *tag = (GtkTextTag *) node->data;
2299 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2300 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2301 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2303 offset = gtk_text_iter_get_offset (&match_start);
2304 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2305 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2309 gtk_text_iter_forward_char (&iter);
2314 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2316 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2317 GtkTextIter real_start, real_end;
2318 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2320 if (gtk_text_iter_compare (start, end) > 0) {
2324 real_start = *start;
2328 GSList *tags = gtk_text_iter_get_tags (&real_start);
2330 for (node = tags; node != NULL; node = g_slist_next (node)) {
2331 GtkTextTag *tag = (GtkTextTag *) node->data;
2332 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2333 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2335 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2337 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2340 } while (gtk_text_iter_forward_char (&real_start)&&
2341 (gtk_text_iter_compare (&real_start, &real_end)<=0));
2345 msg_body_focus (GtkWidget *focus,
2346 GdkEventFocus *event,
2350 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2355 recpt_field_changed (GtkTextBuffer *buffer,
2356 ModestMsgEditWindow *editor)
2358 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2359 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2360 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2361 gboolean dim = FALSE;
2364 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2365 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2366 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2368 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2369 gtk_text_buffer_get_char_count (cc_buffer) +
2370 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2372 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2373 gtk_action_set_sensitive (action, !dim);
2374 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2375 gtk_action_set_sensitive (action, !dim);
2379 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2381 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2385 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2387 gboolean rich_text, editor_focused;
2389 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2390 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2391 editor_focused = gtk_widget_is_focus (priv->msg_body);
2394 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2395 else if (!editor_focused)
2396 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2400 reset_modified (ModestMsgEditWindow *editor)
2402 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2403 GtkTextBuffer *buffer;
2405 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2406 gtk_text_buffer_set_modified (buffer, FALSE);
2407 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2408 gtk_text_buffer_set_modified (buffer, FALSE);
2409 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2410 gtk_text_buffer_set_modified (buffer, FALSE);
2411 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2415 is_modified (ModestMsgEditWindow *editor)
2417 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2418 GtkTextBuffer *buffer;
2420 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2421 if (gtk_text_buffer_get_modified (buffer))
2423 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2424 if (gtk_text_buffer_get_modified (buffer))
2426 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2427 if (gtk_text_buffer_get_modified (buffer))
2429 if (gtk_text_buffer_get_modified (priv->text_buffer))
2436 modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
2438 ModestMsgEditWindowPrivate *priv = NULL;
2440 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2441 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2443 /* check if there's no recipient added */
2444 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2445 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2446 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2447 /* no recipient contents, then select contacts */
2448 modest_msg_edit_window_open_addressbook (window, NULL);
2452 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
2454 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
2456 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
2459 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2466 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2467 ModestMsgEditWindow *window)
2469 modest_msg_edit_window_attach_file (window);
2473 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2475 ModestMsgEditWindow *window)
2477 ModestWindowPrivate *parent_priv;
2482 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2483 selection = gtk_clipboard_wait_for_text (clipboard);
2484 focused = gtk_window_get_focus (GTK_WINDOW (window));
2486 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2487 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2488 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2489 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2493 update_window_title (ModestMsgEditWindow *window)
2495 ModestMsgEditWindowPrivate *priv = NULL;
2496 const gchar *subject;
2498 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2499 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2500 if (subject == NULL || subject[0] == '\0')
2501 subject = _("mail_va_new_email");
2503 gtk_window_set_title (GTK_WINDOW (window), subject);
2508 subject_field_changed (GtkEditable *editable,
2509 ModestMsgEditWindow *window)
2511 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2512 update_window_title (window);
2513 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2517 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2520 ModestMsgEditWindowPrivate *priv = NULL;
2522 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2523 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2525 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2527 gtk_widget_show_all (priv->find_toolbar);
2528 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2530 gtk_widget_hide_all (priv->find_toolbar);
2531 gtk_widget_grab_focus (priv->msg_body);
2537 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2538 ModestMsgEditWindow *window)
2540 gchar *current_search = NULL;
2541 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2543 GtkTextIter selection_start, selection_end;
2544 GtkTextIter match_start, match_end;
2546 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2547 if ((current_search == NULL) && (strcmp (current_search, "") == 0)) {
2548 g_free (current_search);
2552 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2553 result = gtk_text_iter_forward_search (&selection_end, current_search, GTK_TEXT_SEARCH_VISIBLE_ONLY, &match_start, &match_end, NULL);
2555 GtkTextIter buffer_start;
2556 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2557 result = gtk_text_iter_forward_search (&buffer_start, current_search, GTK_TEXT_SEARCH_VISIBLE_ONLY, &match_start, &match_end, &selection_start);
2560 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2561 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2563 /* TODO: warning about non succesful search */
2565 g_free (current_search);
2569 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2570 ModestMsgEditWindow *window)
2572 GtkToggleAction *toggle;
2573 ModestWindowPrivate *parent_priv;
2574 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2576 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2577 gtk_toggle_action_set_active (toggle, FALSE);