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,
1547 ModestMsgEditWindowPrivate *priv;
1549 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1554 file_id = g_open (filename, O_RDONLY, 0);
1555 if (file_id != -1) {
1556 TnyMimePart *mime_part;
1558 const gchar *mime_type;
1562 mime_type = gnome_vfs_get_file_mime_type_fast (filename, NULL);
1563 mime_part = tny_platform_factory_new_mime_part
1564 (modest_runtime_get_platform_factory ());
1565 stream = TNY_STREAM (tny_fs_stream_new (file_id));
1567 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1569 content_id = g_strdup_printf ("%d", priv->last_cid);
1570 tny_mime_part_set_content_id (mime_part, content_id);
1571 g_free (content_id);
1574 basename = g_path_get_basename (filename);
1575 tny_mime_part_set_filename (mime_part, basename);
1578 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1579 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1581 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1582 gtk_widget_show_all (priv->attachments_caption);
1583 } else if (file_id == -1) {
1585 g_warning("file to be attached does not exist: %s", filename);
1591 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1594 ModestMsgEditWindowPrivate *priv;
1595 gboolean clean_list = FALSE;
1597 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1598 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1600 if (att_list == NULL) {
1601 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1605 if (att_list == NULL) {
1606 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1608 GtkWidget *confirmation_dialog = NULL;
1609 gboolean dialog_response;
1611 gchar *message = NULL;
1612 const gchar *filename = NULL;
1614 if (att_list->next == NULL) {
1615 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1619 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1620 att_list->next == NULL), filename);
1621 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1623 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1624 gtk_widget_destroy (confirmation_dialog);
1625 if (!dialog_response) {
1627 g_list_free (att_list);
1630 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1632 for (node = att_list; node != NULL; node = g_list_next (node)) {
1633 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1634 const gchar *att_id;
1635 priv->attachments = g_list_remove (priv->attachments, mime_part);
1637 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1639 if (priv->attachments == NULL)
1640 gtk_widget_hide (priv->attachments_caption);
1641 att_id = tny_mime_part_get_content_id (mime_part);
1643 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1645 g_object_unref (mime_part);
1646 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1651 g_list_free (att_list);
1655 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1658 ModestMsgEditWindowPrivate *priv;
1659 GdkColor *new_color;
1660 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1662 #ifdef MODEST_HILDON_VERSION_0
1663 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1666 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1668 #endif /*MODEST_HILDON_VERSION_0*/
1670 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1672 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1677 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1680 ModestMsgEditWindowPrivate *priv;
1681 gint new_size_index;
1682 ModestMsgEditWindow *window;
1685 window = MODEST_MSG_EDIT_WINDOW (userdata);
1686 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1687 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1689 if (gtk_check_menu_item_get_active (menu_item)) {
1691 WPTextBufferFormat format;
1693 memset (&format, 0, sizeof (format));
1694 wp_text_buffer_get_current_state (WP_TEXT_BUFFER (priv->text_buffer), &format);
1696 label = gtk_bin_get_child (GTK_BIN (menu_item));
1698 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1699 format.cs.font_size = TRUE;
1700 format.cs.text_position = TRUE;
1701 format.cs.font = TRUE;
1702 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1703 wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format);
1705 /* if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, */
1706 /* (gpointer) wp_get_font_size_index (new_size_index, 12))) */
1707 /* wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body)); */
1709 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1710 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1711 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1717 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1720 ModestMsgEditWindowPrivate *priv;
1721 gint new_font_index;
1722 ModestMsgEditWindow *window;
1725 window = MODEST_MSG_EDIT_WINDOW (userdata);
1726 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1727 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1729 if (gtk_check_menu_item_get_active (menu_item)) {
1732 label = gtk_bin_get_child (GTK_BIN (menu_item));
1734 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1736 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1737 (gpointer) new_font_index))
1738 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1740 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1741 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1742 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1748 modest_msg_edit_window_set_zoom (ModestWindow *window,
1751 ModestMsgEditWindowPrivate *priv;
1753 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1755 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1756 priv->zoom_level = zoom;
1757 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom);
1761 modest_msg_edit_window_get_zoom (ModestWindow *window)
1763 ModestMsgEditWindowPrivate *priv;
1765 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1767 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1768 return priv->zoom_level;
1772 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1774 ModestWindowPrivate *parent_priv;
1775 GtkRadioAction *zoom_radio_action;
1776 GSList *group, *node;
1778 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1779 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1780 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1782 group = gtk_radio_action_get_group (zoom_radio_action);
1784 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1785 hildon_banner_show_information (NULL, NULL, _("mcen_ib_max_zoom_level"));
1789 for (node = group; node != NULL; node = g_slist_next (node)) {
1790 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1791 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1799 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1801 ModestWindowPrivate *parent_priv;
1802 GtkRadioAction *zoom_radio_action;
1803 GSList *group, *node;
1805 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1806 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1807 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1809 group = gtk_radio_action_get_group (zoom_radio_action);
1811 for (node = group; node != NULL; node = g_slist_next (node)) {
1812 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1813 if (node->next != NULL) {
1814 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1817 hildon_banner_show_information (NULL, NULL, _("mcen_ib_min_zoom_level"));
1825 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1827 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1828 ModestWindowPrivate *parent_priv;
1829 ModestWindowMgr *mgr;
1830 gboolean is_fullscreen;
1831 GtkAction *fs_toggle_action;
1834 mgr = modest_runtime_get_window_mgr ();
1835 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1837 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1839 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1840 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1841 if (is_fullscreen != active)
1842 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1850 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
1852 ModestWindowPrivate *parent_priv;
1853 GtkAction *fs_toggle_action;
1856 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1858 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1859 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
1860 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
1864 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
1867 ModestMsgEditWindowPrivate *priv = NULL;
1868 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1870 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1871 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1873 gtk_widget_show (priv->cc_caption);
1875 gtk_widget_hide (priv->cc_caption);
1876 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
1880 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
1883 ModestMsgEditWindowPrivate *priv = NULL;
1884 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1886 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1887 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1889 gtk_widget_show (priv->bcc_caption);
1891 gtk_widget_hide (priv->bcc_caption);
1892 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
1896 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
1897 ModestRecptEditor *editor)
1899 ModestMsgEditWindowPrivate *priv;
1901 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1902 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
1903 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1905 if (editor == NULL) {
1906 GtkWidget *view_focus;
1907 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
1909 /* This code should be kept in sync with ModestRecptEditor. The
1910 textview inside the recpt editor is the one that really gets the
1911 focus. As it's inside a scrolled window, and this one inside the
1912 hbox recpt editor inherits from, we'll need to go up in the
1913 hierarchy to know if the text view is part of the recpt editor
1914 or if it's a different text entry */
1916 if (gtk_widget_get_parent (view_focus)) {
1917 GtkWidget *first_parent;
1919 first_parent = gtk_widget_get_parent (view_focus);
1920 if (gtk_widget_get_parent (first_parent) &&
1921 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
1922 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
1927 editor = MODEST_RECPT_EDITOR (priv->to_field);
1931 modest_address_book_select_addresses (editor);
1936 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
1938 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1940 modest_msg_edit_window_open_addressbook (window, NULL);
1944 modest_msg_edit_window_show_toolbar (ModestWindow *self,
1945 gboolean show_toolbar)
1947 ModestWindowPrivate *parent_priv;
1949 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1950 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1952 /* FIXME: we can not just use the code of
1953 modest_msg_edit_window_setup_toolbar because it has a
1954 mixture of both initialization and creation code. */
1957 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1959 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1963 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
1964 TnyHeaderFlags priority_flags)
1966 ModestMsgEditWindowPrivate *priv;
1967 ModestWindowPrivate *parent_priv;
1969 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1971 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1972 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1973 priority_flags = priority_flags & (TNY_HEADER_FLAG_HIGH_PRIORITY);
1975 if (priv->priority_flags != priority_flags) {
1976 GtkAction *priority_action = NULL;
1978 priv->priority_flags = priority_flags;
1980 switch (priority_flags) {
1981 case TNY_HEADER_FLAG_HIGH_PRIORITY:
1982 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
1983 gtk_widget_show (priv->priority_icon);
1984 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1985 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
1987 case TNY_HEADER_FLAG_LOW_PRIORITY:
1988 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
1989 gtk_widget_show (priv->priority_icon);
1990 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1991 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
1994 gtk_widget_hide (priv->priority_icon);
1995 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1996 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
1999 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2000 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2005 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2008 ModestMsgEditWindowPrivate *priv;
2009 gint current_format;
2011 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2013 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2015 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2016 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2018 if (current_format != file_format) {
2019 switch (file_format) {
2020 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2021 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2023 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2027 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2028 response = gtk_dialog_run (GTK_DIALOG (dialog));
2029 gtk_widget_destroy (dialog);
2030 if (response == GTK_RESPONSE_OK)
2031 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2035 update_dimmed (window);
2040 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2043 ModestMsgEditWindowPrivate *priv;
2044 WPTextBufferFormat oldfmt, fmt;
2045 gint old_position = 0;
2049 GdkColor *color = NULL;
2050 gboolean bold, bold_set, italic, italic_set;
2051 gboolean underline, underline_set;
2052 gboolean strikethrough, strikethrough_set;
2053 gboolean position_set;
2054 gboolean font_size_set, font_set, color_set;
2057 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2058 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2060 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2062 /* First we get the currently selected font information */
2063 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2064 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2066 switch (oldfmt.text_position) {
2067 case TEXT_POSITION_NORMAL:
2070 case TEXT_POSITION_SUPERSCRIPT:
2078 g_object_set (G_OBJECT (dialog),
2079 "bold", oldfmt.bold != FALSE,
2080 "bold-set", !oldfmt.cs.bold,
2081 "underline", oldfmt.underline != FALSE,
2082 "underline-set", !oldfmt.cs.underline,
2083 "italic", oldfmt.italic != FALSE,
2084 "italic-set", !oldfmt.cs.italic,
2085 "strikethrough", oldfmt.strikethrough != FALSE,
2086 "strikethrough-set", !oldfmt.cs.strikethrough,
2087 "color", &oldfmt.color,
2088 "color-set", !oldfmt.cs.color,
2089 "size", wp_font_size[oldfmt.font_size],
2090 "size-set", !oldfmt.cs.font_size,
2091 "position", old_position,
2092 "position-set", !oldfmt.cs.text_position,
2093 "family", wp_get_font_name (oldfmt.font),
2094 "family-set", !oldfmt.cs.font,
2097 gtk_widget_show_all (dialog);
2098 response = gtk_dialog_run (GTK_DIALOG (dialog));
2099 if (response == GTK_RESPONSE_OK) {
2101 g_object_get( dialog,
2103 "bold-set", &bold_set,
2104 "underline", &underline,
2105 "underline-set", &underline_set,
2107 "italic-set", &italic_set,
2108 "strikethrough", &strikethrough,
2109 "strikethrough-set", &strikethrough_set,
2111 "color-set", &color_set,
2113 "size-set", &font_size_set,
2114 "family", &font_name,
2115 "family-set", &font_set,
2116 "position", &position,
2117 "position-set", &position_set,
2122 if (response == GTK_RESPONSE_OK) {
2123 memset(&fmt, 0, sizeof(fmt));
2129 fmt.italic = italic;
2130 fmt.cs.italic = TRUE;
2132 if (underline_set) {
2133 fmt.underline = underline;
2134 fmt.cs.underline = TRUE;
2136 if (strikethrough_set) {
2137 fmt.strikethrough = strikethrough;
2138 fmt.cs.strikethrough = TRUE;
2143 ? TEXT_POSITION_NORMAL
2144 : ( ( position == 1 )
2145 ? TEXT_POSITION_SUPERSCRIPT
2146 : TEXT_POSITION_SUBSCRIPT );
2147 fmt.cs.text_position = TRUE;
2151 fmt.cs.color = TRUE;
2154 fmt.font = wp_get_font_index(font_name,
2159 if (font_size_set) {
2160 fmt.font_size = wp_get_font_size_index(
2161 font_size, DEFAULT_FONT_SIZE);
2162 fmt.cs.font_size = TRUE;
2164 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2166 gtk_widget_destroy (dialog);
2168 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2172 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2174 ModestMsgEditWindowPrivate *priv;
2176 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2177 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2179 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2181 update_dimmed (window);
2186 update_dimmed (ModestMsgEditWindow *window)
2188 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2189 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2193 gboolean editor_focused;
2195 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2196 editor_focused = gtk_widget_is_focus (priv->msg_body);
2198 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2199 gtk_action_set_sensitive (action, rich_text && editor_focused);
2200 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2201 gtk_action_set_sensitive (action, rich_text && editor_focused);
2202 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2203 gtk_action_set_sensitive (action, rich_text && editor_focused);
2204 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2205 gtk_action_set_sensitive (action, rich_text && editor_focused);
2206 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2207 gtk_action_set_sensitive (action, rich_text && editor_focused);
2208 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2209 gtk_action_set_sensitive (action, rich_text && editor_focused);
2210 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2211 gtk_action_set_sensitive (action, rich_text && editor_focused);
2212 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2213 gtk_action_set_sensitive (action, rich_text && editor_focused);
2214 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2215 gtk_action_set_sensitive (action, rich_text && editor_focused);
2216 widget = priv->font_color_button;
2217 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2218 widget = priv->font_size_toolitem;
2219 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2220 widget = priv->font_face_toolitem;
2221 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2225 setup_insensitive_handlers (ModestMsgEditWindow *window)
2227 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2228 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2231 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2232 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2233 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2234 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2236 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2237 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2238 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2239 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2240 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2241 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2242 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2243 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2244 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2245 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2246 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
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/AttachmentsMenu/InsertImageMenu");
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, "/ToolBar/ActionsBold");
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, "/ToolBar/ActionsItalics");
2253 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2254 widget = priv->font_color_button;
2255 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2256 widget = priv->font_size_toolitem;
2257 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2258 widget = priv->font_face_toolitem;
2259 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2264 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2266 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2269 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2270 gtk_action_set_sensitive (action, can_undo);
2274 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2277 GtkTextIter match_start, match_end;
2279 if (image_id == NULL)
2282 gtk_text_buffer_get_start_iter (buffer, &iter);
2284 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2285 GSList *tags = gtk_text_iter_get_tags (&match_start);
2287 for (node = tags; node != NULL; node = g_slist_next (node)) {
2288 GtkTextTag *tag = (GtkTextTag *) node->data;
2289 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2290 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2291 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2293 offset = gtk_text_iter_get_offset (&match_start);
2294 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2295 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2299 gtk_text_iter_forward_char (&iter);
2304 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2306 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2307 GtkTextIter real_start, real_end;
2308 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2310 if (gtk_text_iter_compare (start, end) > 0) {
2314 real_start = *start;
2318 GSList *tags = gtk_text_iter_get_tags (&real_start);
2320 for (node = tags; node != NULL; node = g_slist_next (node)) {
2321 GtkTextTag *tag = (GtkTextTag *) node->data;
2322 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2323 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2325 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2327 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2330 } while (gtk_text_iter_forward_char (&real_start)&&
2331 (gtk_text_iter_compare (&real_start, &real_end)<=0));
2335 msg_body_focus (GtkWidget *focus,
2336 GdkEventFocus *event,
2340 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2345 recpt_field_changed (GtkTextBuffer *buffer,
2346 ModestMsgEditWindow *editor)
2348 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2349 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2350 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2351 gboolean dim = FALSE;
2354 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2355 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2356 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2358 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2359 gtk_text_buffer_get_char_count (cc_buffer) +
2360 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2362 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2363 gtk_action_set_sensitive (action, !dim);
2364 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2365 gtk_action_set_sensitive (action, !dim);
2369 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2371 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2375 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2377 gboolean rich_text, editor_focused;
2379 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2380 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2381 editor_focused = gtk_widget_is_focus (priv->msg_body);
2384 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2385 else if (!editor_focused)
2386 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2390 reset_modified (ModestMsgEditWindow *editor)
2392 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2393 GtkTextBuffer *buffer;
2395 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2396 gtk_text_buffer_set_modified (buffer, FALSE);
2397 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2398 gtk_text_buffer_set_modified (buffer, FALSE);
2399 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2400 gtk_text_buffer_set_modified (buffer, FALSE);
2401 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2405 is_modified (ModestMsgEditWindow *editor)
2407 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2408 GtkTextBuffer *buffer;
2410 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2411 if (gtk_text_buffer_get_modified (buffer))
2413 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2414 if (gtk_text_buffer_get_modified (buffer))
2416 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2417 if (gtk_text_buffer_get_modified (buffer))
2419 if (gtk_text_buffer_get_modified (priv->text_buffer))
2426 modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
2428 ModestMsgEditWindowPrivate *priv = NULL;
2430 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2431 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2433 /* check if there's no recipient added */
2434 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2435 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2436 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2437 /* no recipient contents, then select contacts */
2438 modest_msg_edit_window_open_addressbook (window, NULL);
2442 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
2444 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
2446 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
2449 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2456 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2457 ModestMsgEditWindow *window)
2459 modest_msg_edit_window_attach_file (window);
2463 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2465 ModestMsgEditWindow *window)
2467 ModestWindowPrivate *parent_priv;
2472 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2473 selection = gtk_clipboard_wait_for_text (clipboard);
2474 focused = gtk_window_get_focus (GTK_WINDOW (window));
2476 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2477 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2478 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2479 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2483 update_window_title (ModestMsgEditWindow *window)
2485 ModestMsgEditWindowPrivate *priv = NULL;
2486 const gchar *subject;
2488 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2489 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2490 if (subject == NULL || subject[0] == '\0')
2491 subject = _("mail_va_new_email");
2493 gtk_window_set_title (GTK_WINDOW (window), subject);
2498 subject_field_changed (GtkEditable *editable,
2499 ModestMsgEditWindow *window)
2501 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2502 update_window_title (window);
2503 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2507 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2510 ModestMsgEditWindowPrivate *priv = NULL;
2512 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2513 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2515 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2517 gtk_widget_show_all (priv->find_toolbar);
2518 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2520 gtk_widget_hide_all (priv->find_toolbar);
2521 gtk_widget_grab_focus (priv->msg_body);
2527 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2528 ModestMsgEditWindow *window)
2530 gchar *current_search = NULL;
2531 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2533 GtkTextIter selection_start, selection_end;
2534 GtkTextIter match_start, match_end;
2536 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2537 if ((current_search == NULL) && (strcmp (current_search, "") == 0)) {
2538 g_free (current_search);
2542 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2543 result = gtk_text_iter_forward_search (&selection_end, current_search, GTK_TEXT_SEARCH_VISIBLE_ONLY, &match_start, &match_end, NULL);
2545 GtkTextIter buffer_start;
2546 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2547 result = gtk_text_iter_forward_search (&buffer_start, current_search, GTK_TEXT_SEARCH_VISIBLE_ONLY, &match_start, &match_end, &selection_start);
2550 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2551 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2553 /* TODO: warning about non succesful search */
2555 g_free (current_search);
2559 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2560 ModestMsgEditWindow *window)
2562 GtkToggleAction *toggle;
2563 ModestWindowPrivate *parent_priv;
2564 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2566 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2567 gtk_toggle_action_set_active (toggle, FALSE);