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 remove_attachment_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
86 static void setup_insensitive_handlers (ModestMsgEditWindow *editor);
87 static void reset_modified (ModestMsgEditWindow *editor);
88 static gboolean is_modified (ModestMsgEditWindow *editor);
90 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
91 static void text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata);
92 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
93 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
94 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
95 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
97 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
99 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
101 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
102 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
103 GdkEventWindowState *event,
105 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
106 ModestRecptEditor *editor);
107 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
108 ModestMsgEditWindow *window);
110 /* ModestWindow methods implementation */
111 static void modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom);
112 static gdouble modest_msg_edit_window_get_zoom (ModestWindow *window);
113 static gboolean modest_msg_edit_window_zoom_minus (ModestWindow *window);
114 static gboolean modest_msg_edit_window_zoom_plus (ModestWindow *window);
115 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
116 gboolean show_toolbar);
117 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
119 ModestMsgEditWindow *window);
120 static void modest_msg_edit_window_system_clipboard_owner_change (GtkClipboard *clipboard,
122 ModestMsgEditWindow *window);
123 static void update_window_title (ModestMsgEditWindow *window);
124 static void update_dimmed (ModestMsgEditWindow *window);
125 static void update_paste_dimming (ModestMsgEditWindow *window);
126 static void update_select_all_dimming (ModestMsgEditWindow *window);
129 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
130 ModestMsgEditWindow *window);
131 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
132 ModestMsgEditWindow *window);
133 static void edit_menu_activated (GtkAction *action,
136 /* list my signals */
143 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
144 struct _ModestMsgEditWindowPrivate {
146 GtkWidget *header_box;
148 ModestPairList *from_field_protos;
149 GtkWidget *from_field;
153 GtkWidget *bcc_field;
154 GtkWidget *subject_field;
155 GtkWidget *attachments_view;
156 GtkWidget *priority_icon;
157 GtkWidget *add_attachment_button;
159 GtkWidget *cc_caption;
160 GtkWidget *bcc_caption;
161 GtkWidget *attachments_caption;
163 GtkTextBuffer *text_buffer;
165 GtkWidget *font_size_toolitem;
166 GtkWidget *font_face_toolitem;
167 GtkWidget *font_color_button;
168 GSList *font_items_group;
169 GtkWidget *font_tool_button_label;
170 GSList *size_items_group;
171 GtkWidget *size_tool_button_label;
173 GtkWidget *find_toolbar;
180 TnyHeaderFlags priority_flags;
184 gulong clipboard_change_handler_id;
185 gulong system_clipboard_change_handler_id;
190 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
191 MODEST_TYPE_MSG_EDIT_WINDOW, \
192 ModestMsgEditWindowPrivate))
194 static GtkWindowClass *parent_class = NULL;
196 /* uncomment the following if you have defined any signals */
197 /* static guint signals[LAST_SIGNAL] = {0}; */
200 modest_msg_edit_window_get_type (void)
202 static GType my_type = 0;
204 static const GTypeInfo my_info = {
205 sizeof(ModestMsgEditWindowClass),
206 NULL, /* base init */
207 NULL, /* base finalize */
208 (GClassInitFunc) modest_msg_edit_window_class_init,
209 NULL, /* class finalize */
210 NULL, /* class data */
211 sizeof(ModestMsgEditWindow),
213 (GInstanceInitFunc) modest_msg_edit_window_init,
216 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
217 "ModestMsgEditWindow",
220 wp_text_buffer_library_init ();
226 save_state (ModestWindow *self)
228 modest_widget_memory_save (modest_runtime_get_conf(),
229 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
234 restore_settings (ModestMsgEditWindow *self)
236 modest_widget_memory_restore (modest_runtime_get_conf(),
237 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
242 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
244 GObjectClass *gobject_class;
245 ModestWindowClass *modest_window_class;
246 gobject_class = (GObjectClass*) klass;
247 modest_window_class = (ModestWindowClass*) klass;
249 parent_class = g_type_class_peek_parent (klass);
250 gobject_class->finalize = modest_msg_edit_window_finalize;
252 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
253 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
254 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
255 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
256 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
258 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
260 modest_window_class->save_state_func = save_state;
264 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
266 ModestMsgEditWindowPrivate *priv;
267 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
269 priv->msg_body = NULL;
270 priv->from_field = NULL;
271 priv->to_field = NULL;
272 priv->cc_field = NULL;
273 priv->bcc_field = NULL;
274 priv->subject_field = NULL;
275 priv->attachments = NULL;
277 priv->zoom_level = 1.0;
279 priv->cc_caption = NULL;
280 priv->bcc_caption = NULL;
282 priv->priority_flags = 0;
284 priv->find_toolbar = NULL;
286 priv->draft_msg = NULL;
287 priv->clipboard_change_handler_id = 0;
288 priv->system_clipboard_change_handler_id = 0;
292 /* FIXME: this is a dup from the one in gtk/ */
295 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
297 static ModestPairList*
298 get_transports (void)
300 GSList *transports = NULL;
302 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
303 GSList *accounts = modest_account_mgr_account_names (account_mgr,
304 TRUE /* only enabled accounts. */);
306 GSList *cursor = accounts;
308 gchar *account_name = cursor->data;
309 gchar *from_string = NULL;
311 from_string = modest_account_mgr_get_from_string (account_mgr,
315 if (from_string && account_name) {
316 gchar *name = account_name;
317 ModestPair *pair = modest_pair_new ((gpointer) name,
318 (gpointer) from_string , TRUE);
319 transports = g_slist_prepend (transports, pair);
322 cursor = cursor->next;
324 g_slist_free (accounts); /* only free the accounts, not the elements,
325 * because they are used in the pairlist */
331 init_window (ModestMsgEditWindow *obj)
333 GtkWidget *from_caption, *to_caption, *subject_caption;
334 GtkWidget *main_vbox;
335 ModestMsgEditWindowPrivate *priv;
337 GtkSizeGroup *size_group;
339 GtkWidget *scroll_area;
340 GtkWidget *subject_box;
341 GtkWidget *attachment_icon;
342 GtkWidget *window_box;
344 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
346 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
348 /* Note: This ModestPairList* must exist for as long as the combo
349 * that uses it, because the ModestComboBox uses the ID opaquely,
350 * so it can't know how to manage its memory. */
351 priv->from_field_protos = get_transports ();
353 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
355 priv->to_field = modest_recpt_editor_new ();
356 priv->cc_field = modest_recpt_editor_new ();
357 priv->bcc_field = modest_recpt_editor_new ();
358 subject_box = gtk_hbox_new (FALSE, 0);
359 priv->priority_icon = gtk_image_new ();
360 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
361 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
362 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
363 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
364 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
365 priv->add_attachment_button = gtk_button_new ();
366 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
367 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
368 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
369 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
370 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
371 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
372 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
373 priv->attachments_view = modest_attachments_view_new (NULL);
375 priv->header_box = gtk_vbox_new (FALSE, 0);
377 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
378 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
379 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
380 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
381 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
382 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
383 g_object_unref (size_group);
385 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
386 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
387 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
388 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
389 gtk_size_group_add_widget (size_group, priv->subject_field);
390 gtk_size_group_add_widget (size_group, priv->attachments_view);
391 g_object_unref (size_group);
393 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
394 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
395 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
396 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
397 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
398 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
399 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
402 priv->msg_body = wp_text_view_new ();
403 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
404 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
405 g_object_set (priv->text_buffer, "font_scale", 1.0, NULL);
406 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
407 /* gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
408 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
410 priv->find_toolbar = hildon_find_toolbar_new (NULL);
411 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
413 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
414 G_CALLBACK (text_buffer_refresh_attributes), obj);
415 g_signal_connect (G_OBJECT (priv->text_buffer), "delete-range",
416 G_CALLBACK (text_buffer_delete_range), obj);
417 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
418 G_CALLBACK (text_buffer_can_undo), obj);
419 g_signal_connect (G_OBJECT (obj), "window-state-event",
420 G_CALLBACK (modest_msg_edit_window_window_state_event),
422 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
423 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
424 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
425 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
426 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
427 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
429 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
430 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
432 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
433 G_CALLBACK (msg_body_focus), obj);
434 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
435 G_CALLBACK (msg_body_focus), obj);
436 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
437 "changed", G_CALLBACK (recpt_field_changed), obj);
438 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
439 "changed", G_CALLBACK (recpt_field_changed), obj);
440 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
441 "changed", G_CALLBACK (recpt_field_changed), obj);
442 recpt_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
443 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
445 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
446 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
448 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
449 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
450 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
452 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
454 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
455 frame = gtk_frame_new (NULL);
456 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
458 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
459 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
460 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
462 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL)) {
463 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
464 gtk_widget_hide (priv->cc_caption);
466 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL)) {
467 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
468 gtk_widget_hide (priv->bcc_caption);
471 window_box = gtk_vbox_new (FALSE, 0);
472 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
473 gtk_box_pack_end (GTK_BOX (window_box), priv->find_toolbar, FALSE, FALSE, 0);
474 gtk_container_add (GTK_CONTAINER(obj), window_box);
475 scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
476 gtk_container_add (GTK_CONTAINER (frame), scroll_area);
477 gtk_container_set_focus_vadjustment (GTK_CONTAINER (scroll_area),
478 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
480 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
481 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
482 priv->system_clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
483 G_CALLBACK (modest_msg_edit_window_system_clipboard_owner_change), obj);
489 modest_msg_edit_window_finalize (GObject *obj)
491 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
493 if (priv->clipboard_change_handler_id > 0) {
494 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), priv->clipboard_change_handler_id);
495 priv->clipboard_change_handler_id = 0;
498 if (priv->system_clipboard_change_handler_id > 0) {
499 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
500 priv->system_clipboard_change_handler_id);
501 priv->system_clipboard_change_handler_id = 0;
504 /* This had to stay alive for as long as the combobox that used it: */
505 modest_pair_list_free (priv->from_field_protos);
507 G_OBJECT_CLASS(parent_class)->finalize (obj);
511 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMsgEditWindow *self)
513 GtkWidget *close_dialog;
514 ModestMsgEditWindowPrivate *priv;
517 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
518 modest_window_save_state (MODEST_WINDOW (self));
519 if (is_modified (self)) {
520 close_dialog = hildon_note_new_confirmation (GTK_WINDOW (self), _("mcen_nc_no_email_message_modified_save_changes"));
521 response = gtk_dialog_run (GTK_DIALOG (close_dialog));
522 gtk_widget_destroy (close_dialog);
524 if (response != GTK_RESPONSE_CANCEL) {
525 modest_ui_actions_on_save_to_drafts (NULL, self);
528 /* /\* remove old message from drafts *\/ */
529 /* if (priv->draft_msg) { */
530 /* TnyHeader *header = tny_msg_get_header (priv->draft_msg); */
531 /* TnyAccount *account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(), */
533 /* TNY_ACCOUNT_TYPE_STORE); */
534 /* TnyFolder *folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS); */
535 /* g_return_val_if_fail (TNY_IS_HEADER (header), FALSE); */
536 /* g_return_val_if_fail (TNY_IS_FOLDER (folder), FALSE); */
537 /* tny_folder_remove_msg (folder, header, NULL); */
538 /* g_object_unref (folder); */
539 /* g_object_unref (header); */
540 /* g_object_unref (priv->draft_msg); */
541 /* priv->draft_msg = NULL; */
543 gtk_widget_destroy (GTK_WIDGET (self));
549 menubar_to_menu (GtkUIManager *ui_manager)
551 GtkWidget *main_menu;
555 /* Create new main menu */
556 main_menu = gtk_menu_new();
558 /* Get the menubar from the UI manager */
559 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
561 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
565 menu = GTK_WIDGET (iter->data);
566 gtk_widget_reparent(menu, main_menu);
568 iter = g_list_next (iter);
575 set_msg (ModestMsgEditWindow *self, TnyMsg *msg)
578 const gchar *to, *cc, *bcc, *subject;
580 ModestMsgEditWindowPrivate *priv;
582 TnyHeaderFlags priority_flags;
584 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
585 g_return_if_fail (TNY_IS_MSG (msg));
587 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
589 header = tny_msg_get_header (msg);
590 to = tny_header_get_to (header);
591 cc = tny_header_get_cc (header);
592 bcc = tny_header_get_bcc (header);
593 subject = tny_header_get_subject (header);
594 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
597 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
599 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
601 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
603 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
604 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
607 update_window_title (self);
609 /* gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
610 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
611 body = modest_tny_msg_get_body (msg, TRUE);
613 if ((body == NULL)||(body[0] == '\0')) {
615 body = modest_text_utils_convert_to_html ("");
617 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
618 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
621 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
624 /* Get the default format required from configuration */
625 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
626 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
629 /* Set the default focus depending on having already a To: field or not */
630 if ((!to)||(*to == '\0')) {
631 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
633 gtk_widget_grab_focus (priv->msg_body);
636 /* TODO: lower priority, select in the From: combo to the
637 value that comes from msg <- not sure, should it be
640 /* Add attachments to the view */
641 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
642 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
643 if (priv->attachments == NULL) {
644 gtk_widget_hide (priv->attachments_caption);
646 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
647 gtk_widget_show_all (priv->attachments_caption);
650 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
651 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
653 reset_modified (self);
655 update_dimmed (self);
656 text_buffer_can_undo (priv->text_buffer, FALSE, self);
658 priv->draft_msg = msg;
662 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
665 GList *item_children, *node;
666 GtkWidget *bin_child;
668 bin_child = gtk_bin_get_child (GTK_BIN(item));
670 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
672 for (node = item_children; node != NULL; node = g_list_next (node)) {
673 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
674 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
677 g_list_free (item_children);
681 menu_tool_button_dont_expand (GtkMenuToolButton *item)
684 GList *item_children, *node;
686 box = gtk_bin_get_child (GTK_BIN (item));
687 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
688 item_children = gtk_container_get_children (GTK_CONTAINER (box));
690 for (node = item_children; node != NULL; node = g_list_next (node)) {
691 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
692 if (GTK_IS_TOGGLE_BUTTON (node->data))
693 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
694 else if (GTK_IS_BUTTON (node->data))
695 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
697 g_list_free (item_children);
702 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
704 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
705 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
706 GtkWidget *placeholder;
707 GtkWidget *tool_item;
712 GtkWidget *sizes_menu;
713 GtkWidget *fonts_menu;
714 GSList *radio_group = NULL;
719 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
720 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
722 /* should we hide the toolbar? */
723 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
724 gtk_widget_hide (parent_priv->toolbar);
726 /* Font color placeholder */
727 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
728 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
731 tool_item = GTK_WIDGET (gtk_tool_item_new ());
732 priv->font_color_button = hildon_color_button_new ();
733 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
734 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
735 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
736 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
737 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
738 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
739 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
741 /* Font size and face placeholder */
742 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
743 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
745 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
746 priv->size_tool_button_label = gtk_label_new (NULL);
747 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
748 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
749 size_text,"</span>", NULL);
750 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
752 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
753 sizes_menu = gtk_menu_new ();
754 priv->size_items_group = NULL;
756 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
757 GtkWidget *size_menu_item;
759 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
760 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
761 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
762 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
763 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
764 gtk_widget_show (size_menu_item);
766 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
770 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
771 GtkWidget *item = (GtkWidget *) node->data;
772 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
776 priv->size_items_group = g_slist_reverse (priv->size_items_group);
777 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
778 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
779 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
780 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
781 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
782 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
783 priv->font_size_toolitem = tool_item;
786 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
787 priv->font_tool_button_label = gtk_label_new (NULL);
788 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
789 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
791 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
792 fonts_menu = gtk_menu_new ();
793 priv->font_items_group = NULL;
795 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
796 GtkWidget *font_menu_item;
797 GtkWidget *child_label;
799 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
800 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
801 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
802 wp_get_font_name (font_index), "</span>", NULL);
803 gtk_label_set_markup (GTK_LABEL (child_label), markup);
806 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
807 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
808 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
809 gtk_widget_show (font_menu_item);
811 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
814 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
815 GtkWidget *item = (GtkWidget *) node->data;
816 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
819 priv->font_items_group = g_slist_reverse (priv->font_items_group);
820 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
821 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
822 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
823 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
824 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
825 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
826 priv->font_face_toolitem = tool_item;
828 /* Set expand and homogeneous for remaining items */
829 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
830 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
831 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
832 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
833 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
834 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
835 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
836 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
837 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
845 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name)
848 ModestWindowPrivate *parent_priv;
849 ModestMsgEditWindowPrivate *priv;
850 GtkActionGroup *action_group;
851 GError *error = NULL;
852 GdkPixbuf *window_icon = NULL;
855 gboolean prefer_formatted;
857 ModestPair *account_pair = NULL;
859 g_return_val_if_fail (msg, NULL);
860 g_return_val_if_fail (account_name, NULL);
862 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
864 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
865 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
867 parent_priv->ui_manager = gtk_ui_manager_new();
868 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
869 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
871 /* Add common actions */
872 gtk_action_group_add_actions (action_group,
873 modest_msg_edit_action_entries,
874 G_N_ELEMENTS (modest_msg_edit_action_entries),
876 gtk_action_group_add_toggle_actions (action_group,
877 modest_msg_edit_toggle_action_entries,
878 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
880 gtk_action_group_add_radio_actions (action_group,
881 modest_msg_edit_alignment_radio_action_entries,
882 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
884 G_CALLBACK (modest_ui_actions_on_change_justify),
886 gtk_action_group_add_radio_actions (action_group,
887 modest_msg_edit_zoom_action_entries,
888 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
890 G_CALLBACK (modest_ui_actions_on_change_zoom),
892 gtk_action_group_add_radio_actions (action_group,
893 modest_msg_edit_priority_action_entries,
894 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
896 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
898 gtk_action_group_add_radio_actions (action_group,
899 modest_msg_edit_file_format_action_entries,
900 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
901 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
902 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
904 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
905 g_object_unref (action_group);
907 /* Load the UI definition */
908 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
911 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
912 g_clear_error (&error);
915 /* Add accelerators */
916 gtk_window_add_accel_group (GTK_WINDOW (obj),
917 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
920 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
921 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
924 init_window (MODEST_MSG_EDIT_WINDOW(obj));
926 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
928 gtk_window_set_icon_from_file (GTK_WINDOW(obj), MODEST_APP_ICON, NULL);
930 g_signal_connect (G_OBJECT(obj), "delete-event",
931 G_CALLBACK(on_delete_event), obj);
933 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
935 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
937 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
939 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
940 if (account_pair != NULL)
941 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
943 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg);
945 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
947 /* Set window icon */
948 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
949 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
951 /* Dim at start clipboard actions */
952 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
953 gtk_action_set_sensitive (action, FALSE);
954 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
955 gtk_action_set_sensitive (action, FALSE);
956 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
957 gtk_action_set_sensitive (action, FALSE);
959 /* Update select all */
960 update_select_all_dimming (MODEST_MSG_EDIT_WINDOW (obj));
961 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu");
962 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (edit_menu_activated), obj);
964 /* set initial state of cc and bcc */
965 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
966 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
967 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
968 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
969 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
970 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
972 /* Setup the file format */
973 conf = modest_runtime_get_conf ();
974 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
976 g_clear_error (&error);
977 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
979 file_format = (prefer_formatted) ?
980 MODEST_FILE_FORMAT_FORMATTED_TEXT :
981 MODEST_FILE_FORMAT_PLAIN_TEXT;
982 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
984 update_paste_dimming (MODEST_MSG_EDIT_WINDOW (obj));
986 return (ModestWindow*) obj;
990 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
992 GString **string_buffer = (GString **) user_data;
994 *string_buffer = g_string_append (*string_buffer, buffer);
1000 * @result: A new string which should be freed with g_free().
1003 get_formatted_data (ModestMsgEditWindow *edit_window)
1005 ModestMsgEditWindowPrivate *priv;
1006 GString *string_buffer = g_string_new ("");
1008 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1010 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1012 return g_string_free (string_buffer, FALSE);
1017 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1020 const gchar *account_name;
1021 ModestMsgEditWindowPrivate *priv;
1023 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1025 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1027 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1028 g_return_val_if_fail (account_name, NULL);
1031 /* don't free these (except from) */
1032 data = g_slice_new0 (MsgData);
1033 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1035 data->account_name = g_strdup (account_name);
1036 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1037 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1038 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1039 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1040 if (priv->draft_msg) {
1041 data->draft_msg = g_object_ref (priv->draft_msg);
1043 data->draft_msg = NULL;
1046 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1048 gtk_text_buffer_get_bounds (buf, &b, &e);
1049 data->plain_body = g_strdup (gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE)); /* returns a copy */
1051 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1052 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1054 data->html_body = NULL;
1056 data->attachments = priv->attachments; /* TODO: copy and free ? */
1057 data->priority_flags = priv->priority_flags;
1062 /* TODO: We must duplicate this implementation for GNOME and Maemo, but that is unwise. */
1064 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1067 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1075 g_free (data->subject);
1076 g_free (data->plain_body);
1077 g_free (data->html_body);
1078 if (data->draft_msg != NULL) {
1079 g_object_unref (data->draft_msg);
1080 data->draft_msg = NULL;
1082 g_free (data->account_name);
1084 /* TODO: Free data->attachments? */
1086 g_slice_free (MsgData, data);
1090 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1093 ModestMsgEditWindowPrivate *priv = NULL;
1094 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1096 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1098 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1100 return MODEST_MSG_EDIT_FORMAT_HTML;
1102 return MODEST_MSG_EDIT_FORMAT_TEXT;
1106 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1107 ModestMsgEditFormat format)
1109 ModestMsgEditWindowPrivate *priv;
1111 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1112 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1115 case MODEST_MSG_EDIT_FORMAT_HTML:
1116 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1118 case MODEST_MSG_EDIT_FORMAT_TEXT:
1119 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1122 g_return_if_reached ();
1126 ModestMsgEditFormatState *
1127 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1129 ModestMsgEditFormatState *format_state = NULL;
1130 ModestMsgEditWindowPrivate *priv;
1131 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1133 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1134 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1136 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1138 format_state = g_new0 (ModestMsgEditFormatState, 1);
1139 format_state->bold = buffer_format->bold&0x1;
1140 format_state->italics = buffer_format->italic&0x1;
1141 format_state->bullet = buffer_format->bullet&0x1;
1142 format_state->color = buffer_format->color;
1143 format_state->font_size = buffer_format->font_size;
1144 format_state->font_family = wp_get_font_name (buffer_format->font);
1145 format_state->justification = buffer_format->justification;
1146 g_free (buffer_format);
1148 return format_state;
1153 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1154 const ModestMsgEditFormatState *format_state)
1156 ModestMsgEditWindowPrivate *priv;
1157 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1158 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1159 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1160 g_return_if_fail (format_state != NULL);
1162 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1163 gtk_widget_grab_focus (priv->msg_body);
1164 buffer_format->bold = (format_state->bold != FALSE);
1165 buffer_format->italic = (format_state->italics != FALSE);
1166 buffer_format->color = format_state->color;
1167 buffer_format->font_size = format_state->font_size;
1168 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1169 buffer_format->justification = format_state->justification;
1170 buffer_format->bullet = format_state->bullet;
1172 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1174 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1175 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1176 buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
1177 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1178 buffer_format->cs.font = (buffer_format->font != current_format->font);
1179 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1180 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1182 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1183 if (buffer_format->cs.bold) {
1184 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1186 if (buffer_format->cs.italic) {
1187 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1189 if (buffer_format->cs.color) {
1190 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1192 if (buffer_format->cs.font_size) {
1193 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->font_size));
1195 if (buffer_format->cs.justification) {
1196 switch (buffer_format->justification) {
1197 case GTK_JUSTIFY_LEFT:
1198 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1200 case GTK_JUSTIFY_CENTER:
1201 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1203 case GTK_JUSTIFY_RIGHT:
1204 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1211 if (buffer_format->cs.font) {
1212 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->font));
1214 if (buffer_format->cs.bullet) {
1215 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((int)buffer_format->bullet));
1217 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1218 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1220 g_free (current_format);
1225 toggle_action_set_active_block_notify (GtkToggleAction *action,
1228 GSList *proxies = NULL;
1230 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1231 proxies != NULL; proxies = g_slist_next (proxies)) {
1232 GtkWidget *widget = (GtkWidget *) proxies->data;
1233 gtk_action_block_activate_from (GTK_ACTION (action), widget);
1236 gtk_toggle_action_set_active (action, value);
1238 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1239 proxies != NULL; proxies = g_slist_next (proxies)) {
1240 GtkWidget *widget = (GtkWidget *) proxies->data;
1241 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
1246 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1248 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1250 ModestWindowPrivate *parent_priv;
1251 ModestMsgEditWindowPrivate *priv;
1252 GtkWidget *new_size_menuitem;
1253 GtkWidget *new_font_menuitem;
1255 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1256 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1258 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1259 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1260 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1261 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1263 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1264 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1265 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1268 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1270 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1271 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1273 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1274 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1276 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1277 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1279 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1280 G_CALLBACK (modest_msg_edit_window_color_button_change),
1282 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1283 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1284 G_CALLBACK (modest_msg_edit_window_color_button_change),
1287 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1288 buffer_format->font_size))->data);
1289 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1293 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1294 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1295 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1297 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1298 G_CALLBACK (modest_msg_edit_window_size_change),
1300 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1301 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1302 G_CALLBACK (modest_msg_edit_window_size_change),
1306 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1307 buffer_format->font))->data);
1308 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1312 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1313 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1314 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1316 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1317 G_CALLBACK (modest_msg_edit_window_font_change),
1319 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1320 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1321 G_CALLBACK (modest_msg_edit_window_font_change),
1325 g_free (buffer_format);
1331 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1334 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1335 ModestMsgEditWindowPrivate *priv;
1336 GtkWidget *dialog = NULL;
1338 const GdkColor *new_color = NULL;
1340 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1341 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1343 #ifdef MODEST_HILDON_VERSION_0
1344 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1345 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1347 dialog = hildon_color_chooser_new ();
1348 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1349 #endif /*MODEST_HILDON_VERSION_0*/
1350 g_free (buffer_format);
1352 response = gtk_dialog_run (GTK_DIALOG (dialog));
1354 case GTK_RESPONSE_OK: {
1355 #ifdef MODEST_HILDON_VERSION_0
1356 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1359 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1361 #endif /*MODEST_HILDON_VERSION_0*/
1368 gtk_widget_destroy (dialog);
1370 if (new_color != NULL)
1371 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1376 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1379 ModestMsgEditWindowPrivate *priv;
1380 GtkWidget *dialog = NULL;
1382 GdkColor *old_color = NULL;
1383 const GdkColor *new_color = NULL;
1385 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1386 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1388 #ifdef MODEST_HILDON_VERSION_0
1389 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1390 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1392 dialog = hildon_color_chooser_new ();
1393 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1394 #endif /*MODEST_HILDON_VERSION_9*/
1396 response = gtk_dialog_run (GTK_DIALOG (dialog));
1398 case GTK_RESPONSE_OK: {
1399 #ifdef MODEST_HILDON_VERSION_0
1400 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1403 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1405 #endif /*MODEST_HILDON_VERSION_0*/
1411 gtk_widget_destroy (dialog);
1413 if (new_color != NULL)
1414 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1419 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1422 ModestMsgEditWindowPrivate *priv;
1423 GtkWidget *dialog = NULL;
1425 gchar *filename = NULL;
1427 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1429 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1430 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1432 response = gtk_dialog_run (GTK_DIALOG (dialog));
1434 case GTK_RESPONSE_OK:
1435 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1440 gtk_widget_destroy (dialog);
1443 GdkPixbuf *pixbuf = NULL;
1444 GtkTextIter position;
1445 GtkTextMark *insert_mark;
1447 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
1450 GdkPixbufFormat *pixbuf_format;
1452 image_file_id = g_open (filename, O_RDONLY, 0);
1453 pixbuf_format = gdk_pixbuf_get_file_info (filename, NULL, NULL);
1454 if ((image_file_id != -1)&&(pixbuf_format != NULL)) {
1455 TnyMimePart *image_part;
1456 TnyStream *image_stream;
1462 mime_types = gdk_pixbuf_format_get_mime_types (pixbuf_format);
1463 if ((mime_types != NULL) && (mime_types[0] != NULL)) {
1464 mime_type = mime_types[0];
1466 mime_type = "image/unknown";
1468 image_part = tny_platform_factory_new_mime_part
1469 (modest_runtime_get_platform_factory ());
1470 image_stream = TNY_STREAM (tny_fs_stream_new (image_file_id));
1472 tny_mime_part_construct_from_stream (image_part, image_stream, mime_type);
1473 g_strfreev (mime_types);
1475 content_id = g_strdup_printf ("%d", priv->last_cid);
1476 tny_mime_part_set_content_id (image_part, content_id);
1477 g_free (content_id);
1480 basename = g_path_get_basename (filename);
1481 tny_mime_part_set_filename (image_part, basename);
1484 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1485 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1486 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (image_part)), pixbuf);
1487 priv->attachments = g_list_prepend (priv->attachments, image_part);
1488 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1490 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1491 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1492 gtk_widget_show_all (priv->attachments_caption);
1493 } else if (image_file_id == -1) {
1494 close (image_file_id);
1503 modest_msg_edit_window_attach_file (ModestMsgEditWindow *window)
1506 ModestMsgEditWindowPrivate *priv;
1507 GtkWidget *dialog = NULL;
1509 GSList *uris = NULL;
1512 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1514 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1515 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1517 response = gtk_dialog_run (GTK_DIALOG (dialog));
1519 case GTK_RESPONSE_OK:
1520 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1525 gtk_widget_destroy (dialog);
1527 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1529 GnomeVFSHandle *handle = NULL;
1530 GnomeVFSResult result;
1532 uri = (const gchar *) uri_node->data;
1533 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1534 if (result == GNOME_VFS_OK) {
1535 TnyMimePart *mime_part;
1537 const gchar *mime_type = NULL;
1541 GnomeVFSFileInfo info;
1543 filename = g_filename_from_uri (uri, NULL, NULL);
1545 if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE) == GNOME_VFS_OK)
1546 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1547 mime_part = tny_platform_factory_new_mime_part
1548 (modest_runtime_get_platform_factory ());
1549 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1551 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1553 content_id = g_strdup_printf ("%d", priv->last_cid);
1554 tny_mime_part_set_content_id (mime_part, content_id);
1555 g_free (content_id);
1558 basename = g_path_get_basename (filename);
1559 tny_mime_part_set_filename (mime_part, basename);
1562 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1563 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1565 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1566 gtk_widget_show_all (priv->attachments_caption);
1567 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1572 g_slist_foreach (uris, (GFunc) g_free, NULL);
1573 g_slist_free (uris);
1577 modest_msg_edit_window_attach_file_noninteractive (
1578 ModestMsgEditWindow *window,
1579 const gchar *file_uri)
1582 ModestMsgEditWindowPrivate *priv;
1584 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1589 /* TODO: We should probably try to use only the URI,
1590 * instead of using a filename.
1592 gchar* filename = g_filename_from_uri (file_uri, NULL, NULL);
1594 g_warning("%s: g_filename_from_uri(%s) failed.\n", __FUNCTION__, file_uri);
1597 file_id = g_open (filename, O_RDONLY, 0);
1598 if (file_id != -1) {
1599 TnyMimePart *mime_part;
1601 const gchar *mime_type;
1605 mime_type = gnome_vfs_get_file_mime_type_fast (filename, NULL);
1606 mime_part = tny_platform_factory_new_mime_part
1607 (modest_runtime_get_platform_factory ());
1608 stream = TNY_STREAM (tny_fs_stream_new (file_id));
1610 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1612 content_id = g_strdup_printf ("%d", priv->last_cid);
1613 tny_mime_part_set_content_id (mime_part, content_id);
1614 g_free (content_id);
1617 basename = g_path_get_basename (filename);
1618 tny_mime_part_set_filename (mime_part, basename);
1621 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1622 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1624 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1625 gtk_widget_show_all (priv->attachments_caption);
1626 } else if (file_id == -1) {
1628 g_warning("file to be attached does not exist: %s", filename);
1636 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1639 ModestMsgEditWindowPrivate *priv;
1640 gboolean clean_list = FALSE;
1642 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1643 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1645 if (att_list == NULL) {
1646 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1650 if (att_list == NULL) {
1651 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1653 GtkWidget *confirmation_dialog = NULL;
1654 gboolean dialog_response;
1656 gchar *message = NULL;
1657 const gchar *filename = NULL;
1659 if (att_list->next == NULL) {
1660 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1664 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1665 att_list->next == NULL), filename);
1666 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1668 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1669 gtk_widget_destroy (confirmation_dialog);
1670 if (!dialog_response) {
1672 g_list_free (att_list);
1675 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1677 for (node = att_list; node != NULL; node = g_list_next (node)) {
1678 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1679 const gchar *att_id;
1680 priv->attachments = g_list_remove (priv->attachments, mime_part);
1682 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1684 if (priv->attachments == NULL)
1685 gtk_widget_hide (priv->attachments_caption);
1686 att_id = tny_mime_part_get_content_id (mime_part);
1688 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1690 g_object_unref (mime_part);
1691 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1696 g_list_free (att_list);
1700 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1703 ModestMsgEditWindowPrivate *priv;
1704 GdkColor *new_color;
1705 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1707 #ifdef MODEST_HILDON_VERSION_0
1708 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1711 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1713 #endif /*MODEST_HILDON_VERSION_0*/
1715 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1717 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1722 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1725 ModestMsgEditWindowPrivate *priv;
1726 gint new_size_index;
1727 ModestMsgEditWindow *window;
1730 window = MODEST_MSG_EDIT_WINDOW (userdata);
1731 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1732 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1734 if (gtk_check_menu_item_get_active (menu_item)) {
1736 WPTextBufferFormat format;
1738 memset (&format, 0, sizeof (format));
1739 wp_text_buffer_get_current_state (WP_TEXT_BUFFER (priv->text_buffer), &format);
1741 label = gtk_bin_get_child (GTK_BIN (menu_item));
1743 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1744 format.cs.font_size = TRUE;
1745 format.cs.text_position = TRUE;
1746 format.cs.font = TRUE;
1747 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1748 wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format);
1750 /* if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, */
1751 /* (gpointer) wp_get_font_size_index (new_size_index, 12))) */
1752 /* wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body)); */
1754 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1755 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1756 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1762 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1765 ModestMsgEditWindowPrivate *priv;
1766 gint new_font_index;
1767 ModestMsgEditWindow *window;
1770 window = MODEST_MSG_EDIT_WINDOW (userdata);
1771 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1772 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1774 if (gtk_check_menu_item_get_active (menu_item)) {
1777 label = gtk_bin_get_child (GTK_BIN (menu_item));
1779 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1781 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1782 (gpointer) new_font_index))
1783 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1785 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1786 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1787 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1793 modest_msg_edit_window_set_zoom (ModestWindow *window,
1796 ModestMsgEditWindowPrivate *priv;
1798 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1800 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1801 priv->zoom_level = zoom;
1802 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom);
1806 modest_msg_edit_window_get_zoom (ModestWindow *window)
1808 ModestMsgEditWindowPrivate *priv;
1810 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1812 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1813 return priv->zoom_level;
1817 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1819 ModestWindowPrivate *parent_priv;
1820 GtkRadioAction *zoom_radio_action;
1821 GSList *group, *node;
1823 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1824 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1825 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1827 group = gtk_radio_action_get_group (zoom_radio_action);
1829 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1830 hildon_banner_show_information (NULL, NULL, _("ckct_ib_max_zoom_level_reached"));
1834 for (node = group; node != NULL; node = g_slist_next (node)) {
1835 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1836 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1844 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1846 ModestWindowPrivate *parent_priv;
1847 GtkRadioAction *zoom_radio_action;
1848 GSList *group, *node;
1850 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1851 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1852 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1854 group = gtk_radio_action_get_group (zoom_radio_action);
1856 for (node = group; node != NULL; node = g_slist_next (node)) {
1857 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1858 if (node->next != NULL) {
1859 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1862 hildon_banner_show_information (NULL, NULL, _("ckct_ib_min_zoom_level_reached"));
1870 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1872 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1873 ModestWindowPrivate *parent_priv;
1874 ModestWindowMgr *mgr;
1875 gboolean is_fullscreen;
1876 GtkAction *fs_toggle_action;
1879 mgr = modest_runtime_get_window_mgr ();
1880 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1882 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1884 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1885 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1886 if (is_fullscreen != active)
1887 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1895 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
1897 ModestWindowPrivate *parent_priv;
1898 GtkAction *fs_toggle_action;
1901 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1903 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1904 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
1905 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
1909 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
1912 ModestMsgEditWindowPrivate *priv = NULL;
1913 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1915 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1916 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1918 gtk_widget_show (priv->cc_caption);
1920 gtk_widget_hide (priv->cc_caption);
1921 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
1925 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
1928 ModestMsgEditWindowPrivate *priv = NULL;
1929 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1931 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1932 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1934 gtk_widget_show (priv->bcc_caption);
1936 gtk_widget_hide (priv->bcc_caption);
1937 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
1941 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
1942 ModestRecptEditor *editor)
1944 ModestMsgEditWindowPrivate *priv;
1946 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1947 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
1948 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1950 if (editor == NULL) {
1951 GtkWidget *view_focus;
1952 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
1954 /* This code should be kept in sync with ModestRecptEditor. The
1955 textview inside the recpt editor is the one that really gets the
1956 focus. As it's inside a scrolled window, and this one inside the
1957 hbox recpt editor inherits from, we'll need to go up in the
1958 hierarchy to know if the text view is part of the recpt editor
1959 or if it's a different text entry */
1961 if (gtk_widget_get_parent (view_focus)) {
1962 GtkWidget *first_parent;
1964 first_parent = gtk_widget_get_parent (view_focus);
1965 if (gtk_widget_get_parent (first_parent) &&
1966 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
1967 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
1972 editor = MODEST_RECPT_EDITOR (priv->to_field);
1976 modest_address_book_select_addresses (editor);
1981 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
1983 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1985 modest_msg_edit_window_open_addressbook (window, NULL);
1989 modest_msg_edit_window_show_toolbar (ModestWindow *self,
1990 gboolean show_toolbar)
1992 ModestWindowPrivate *parent_priv;
1994 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1995 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1997 /* FIXME: we can not just use the code of
1998 modest_msg_edit_window_setup_toolbar because it has a
1999 mixture of both initialization and creation code. */
2002 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2004 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2008 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2009 TnyHeaderFlags priority_flags)
2011 ModestMsgEditWindowPrivate *priv;
2012 ModestWindowPrivate *parent_priv;
2014 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2016 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2017 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2018 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2020 if (priv->priority_flags != priority_flags) {
2021 GtkAction *priority_action = NULL;
2023 priv->priority_flags = priority_flags;
2025 switch (priority_flags) {
2026 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2027 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2028 gtk_widget_show (priv->priority_icon);
2029 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2030 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2032 case TNY_HEADER_FLAG_LOW_PRIORITY:
2033 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2034 gtk_widget_show (priv->priority_icon);
2035 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2036 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2039 gtk_widget_hide (priv->priority_icon);
2040 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2041 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2044 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2045 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2050 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2053 ModestMsgEditWindowPrivate *priv;
2054 gint current_format;
2056 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2058 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2060 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2061 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2063 if (current_format != file_format) {
2064 switch (file_format) {
2065 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2066 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2068 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2072 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2073 response = gtk_dialog_run (GTK_DIALOG (dialog));
2074 gtk_widget_destroy (dialog);
2075 if (response == GTK_RESPONSE_OK)
2076 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2080 update_dimmed (window);
2085 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2088 ModestMsgEditWindowPrivate *priv;
2089 WPTextBufferFormat oldfmt, fmt;
2090 gint old_position = 0;
2094 GdkColor *color = NULL;
2095 gboolean bold, bold_set, italic, italic_set;
2096 gboolean underline, underline_set;
2097 gboolean strikethrough, strikethrough_set;
2098 gboolean position_set;
2099 gboolean font_size_set, font_set, color_set;
2102 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2103 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2105 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2107 /* First we get the currently selected font information */
2108 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2109 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2111 switch (oldfmt.text_position) {
2112 case TEXT_POSITION_NORMAL:
2115 case TEXT_POSITION_SUPERSCRIPT:
2123 g_object_set (G_OBJECT (dialog),
2124 "bold", oldfmt.bold != FALSE,
2125 "bold-set", !oldfmt.cs.bold,
2126 "underline", oldfmt.underline != FALSE,
2127 "underline-set", !oldfmt.cs.underline,
2128 "italic", oldfmt.italic != FALSE,
2129 "italic-set", !oldfmt.cs.italic,
2130 "strikethrough", oldfmt.strikethrough != FALSE,
2131 "strikethrough-set", !oldfmt.cs.strikethrough,
2132 "color", &oldfmt.color,
2133 "color-set", !oldfmt.cs.color,
2134 "size", wp_font_size[oldfmt.font_size],
2135 "size-set", !oldfmt.cs.font_size,
2136 "position", old_position,
2137 "position-set", !oldfmt.cs.text_position,
2138 "family", wp_get_font_name (oldfmt.font),
2139 "family-set", !oldfmt.cs.font,
2142 gtk_widget_show_all (dialog);
2143 response = gtk_dialog_run (GTK_DIALOG (dialog));
2144 if (response == GTK_RESPONSE_OK) {
2146 g_object_get( dialog,
2148 "bold-set", &bold_set,
2149 "underline", &underline,
2150 "underline-set", &underline_set,
2152 "italic-set", &italic_set,
2153 "strikethrough", &strikethrough,
2154 "strikethrough-set", &strikethrough_set,
2156 "color-set", &color_set,
2158 "size-set", &font_size_set,
2159 "family", &font_name,
2160 "family-set", &font_set,
2161 "position", &position,
2162 "position-set", &position_set,
2167 if (response == GTK_RESPONSE_OK) {
2168 memset(&fmt, 0, sizeof(fmt));
2174 fmt.italic = italic;
2175 fmt.cs.italic = TRUE;
2177 if (underline_set) {
2178 fmt.underline = underline;
2179 fmt.cs.underline = TRUE;
2181 if (strikethrough_set) {
2182 fmt.strikethrough = strikethrough;
2183 fmt.cs.strikethrough = TRUE;
2188 ? TEXT_POSITION_NORMAL
2189 : ( ( position == 1 )
2190 ? TEXT_POSITION_SUPERSCRIPT
2191 : TEXT_POSITION_SUBSCRIPT );
2192 fmt.cs.text_position = TRUE;
2196 fmt.cs.color = TRUE;
2199 fmt.font = wp_get_font_index(font_name,
2204 if (font_size_set) {
2205 fmt.font_size = wp_get_font_size_index(
2206 font_size, DEFAULT_FONT_SIZE);
2207 fmt.cs.font_size = TRUE;
2209 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2211 gtk_widget_destroy (dialog);
2213 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2217 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2219 ModestMsgEditWindowPrivate *priv;
2221 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2222 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2224 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2226 update_dimmed (window);
2231 update_dimmed (ModestMsgEditWindow *window)
2233 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2234 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2238 gboolean editor_focused;
2240 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2241 editor_focused = gtk_widget_is_focus (priv->msg_body);
2243 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2244 gtk_action_set_sensitive (action, rich_text && editor_focused);
2245 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2246 gtk_action_set_sensitive (action, rich_text && editor_focused);
2247 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2248 gtk_action_set_sensitive (action, rich_text && editor_focused);
2249 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2250 gtk_action_set_sensitive (action, rich_text && editor_focused);
2251 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2252 gtk_action_set_sensitive (action, rich_text && editor_focused);
2253 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2254 gtk_action_set_sensitive (action, rich_text && editor_focused);
2255 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2256 gtk_action_set_sensitive (action, rich_text && editor_focused);
2257 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2258 gtk_action_set_sensitive (action, rich_text && editor_focused);
2259 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2260 gtk_action_set_sensitive (action, rich_text && editor_focused);
2261 widget = priv->font_color_button;
2262 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2263 widget = priv->font_size_toolitem;
2264 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2265 widget = priv->font_face_toolitem;
2266 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2270 setup_insensitive_handlers (ModestMsgEditWindow *window)
2272 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2273 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2276 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2277 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2278 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2279 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2281 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2282 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2283 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2284 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2285 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2286 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2287 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2288 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2289 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2290 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2291 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2292 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2293 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2294 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2295 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2296 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2297 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2298 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2299 widget = priv->font_color_button;
2300 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2301 widget = priv->font_size_toolitem;
2302 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2303 widget = priv->font_face_toolitem;
2304 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2306 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2307 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (remove_attachment_insensitive_press), window);
2311 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2313 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2316 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2317 gtk_action_set_sensitive (action, can_undo);
2321 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2324 GtkTextIter match_start, match_end;
2326 if (image_id == NULL)
2329 gtk_text_buffer_get_start_iter (buffer, &iter);
2331 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2332 GSList *tags = gtk_text_iter_get_tags (&match_start);
2334 for (node = tags; node != NULL; node = g_slist_next (node)) {
2335 GtkTextTag *tag = (GtkTextTag *) node->data;
2336 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2337 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2338 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2340 offset = gtk_text_iter_get_offset (&match_start);
2341 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2342 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2346 gtk_text_iter_forward_char (&iter);
2351 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2353 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2354 GtkTextIter real_start, real_end;
2355 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2357 if (gtk_text_iter_compare (start, end) > 0) {
2361 real_start = *start;
2365 GSList *tags = gtk_text_iter_get_tags (&real_start);
2367 for (node = tags; node != NULL; node = g_slist_next (node)) {
2368 GtkTextTag *tag = (GtkTextTag *) node->data;
2369 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2370 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2372 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2374 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2377 } while (gtk_text_iter_forward_char (&real_start)&&
2378 (gtk_text_iter_compare (&real_start, &real_end)<=0));
2382 msg_body_focus (GtkWidget *focus,
2383 GdkEventFocus *event,
2387 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2392 recpt_field_changed (GtkTextBuffer *buffer,
2393 ModestMsgEditWindow *editor)
2395 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2396 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2397 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2398 gboolean dim = FALSE;
2401 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2402 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2403 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2405 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2406 gtk_text_buffer_get_char_count (cc_buffer) +
2407 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2409 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2410 gtk_action_set_sensitive (action, !dim);
2411 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2412 gtk_action_set_sensitive (action, !dim);
2416 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2418 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2422 remove_attachment_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2424 ModestWindowPrivate *parent_priv;
2425 ModestMsgEditWindowPrivate *priv;
2426 GList *selected_attachments = NULL;
2427 gint n_att_selected = 0;
2429 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2430 parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2432 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2433 n_att_selected = g_list_length (selected_attachments);
2434 g_list_free (selected_attachments);
2436 if (n_att_selected > 1)
2437 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unable_to_display_more"));
2438 else if (n_att_selected == 0)
2439 hildon_banner_show_information (NULL, NULL, _("TODO: select one attachment"));
2444 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2446 gboolean rich_text, editor_focused;
2448 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2449 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2450 editor_focused = gtk_widget_is_focus (priv->msg_body);
2453 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2454 else if (!editor_focused)
2455 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2459 reset_modified (ModestMsgEditWindow *editor)
2461 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2462 GtkTextBuffer *buffer;
2464 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2465 gtk_text_buffer_set_modified (buffer, FALSE);
2466 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2467 gtk_text_buffer_set_modified (buffer, FALSE);
2468 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2469 gtk_text_buffer_set_modified (buffer, FALSE);
2470 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2474 is_modified (ModestMsgEditWindow *editor)
2476 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2477 GtkTextBuffer *buffer;
2479 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2480 if (gtk_text_buffer_get_modified (buffer))
2482 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2483 if (gtk_text_buffer_get_modified (buffer))
2485 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2486 if (gtk_text_buffer_get_modified (buffer))
2488 if (gtk_text_buffer_get_modified (priv->text_buffer))
2495 modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
2497 ModestMsgEditWindowPrivate *priv = NULL;
2499 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2500 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2502 /* check if there's no recipient added */
2503 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2504 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2505 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2506 /* no recipient contents, then select contacts */
2507 modest_msg_edit_window_open_addressbook (window, NULL);
2511 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
2513 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
2515 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
2518 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2525 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2526 ModestMsgEditWindow *window)
2528 modest_msg_edit_window_attach_file (window);
2532 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2534 ModestMsgEditWindow *window)
2536 ModestWindowPrivate *parent_priv;
2537 ModestMsgEditWindowPrivate *priv;
2541 GList *selected_attachments = NULL;
2542 gint n_att_selected = 0;
2544 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2545 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2546 selection = gtk_clipboard_wait_for_text (clipboard);
2547 focused = gtk_window_get_focus (GTK_WINDOW (window));
2549 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2550 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2551 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2552 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2554 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2555 n_att_selected = g_list_length (selected_attachments);
2556 g_list_free (selected_attachments);
2558 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2559 gtk_action_set_sensitive (action, n_att_selected == 1);
2562 update_paste_dimming (window);
2566 update_window_title (ModestMsgEditWindow *window)
2568 ModestMsgEditWindowPrivate *priv = NULL;
2569 const gchar *subject;
2571 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2572 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2573 if (subject == NULL || subject[0] == '\0')
2574 subject = _("mail_va_new_email");
2576 gtk_window_set_title (GTK_WINDOW (window), subject);
2581 subject_field_changed (GtkEditable *editable,
2582 ModestMsgEditWindow *window)
2584 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2585 update_window_title (window);
2586 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2590 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2593 ModestMsgEditWindowPrivate *priv = NULL;
2595 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2596 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2598 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2600 gtk_widget_show_all (priv->find_toolbar);
2601 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2603 gtk_widget_hide_all (priv->find_toolbar);
2604 gtk_widget_grab_focus (priv->msg_body);
2610 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2611 ModestMsgEditWindow *window)
2613 gchar *current_search = NULL;
2614 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2616 GtkTextIter selection_start, selection_end;
2617 GtkTextIter match_start, match_end;
2619 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2620 if ((current_search == NULL) && (strcmp (current_search, "") == 0)) {
2621 g_free (current_search);
2625 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2626 result = gtk_text_iter_forward_search (&selection_end, current_search, GTK_TEXT_SEARCH_VISIBLE_ONLY, &match_start, &match_end, NULL);
2628 GtkTextIter buffer_start;
2629 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2630 result = gtk_text_iter_forward_search (&buffer_start, current_search, GTK_TEXT_SEARCH_VISIBLE_ONLY, &match_start, &match_end, &selection_start);
2633 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2634 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2636 /* TODO: warning about non succesful search */
2638 g_free (current_search);
2642 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2643 ModestMsgEditWindow *window)
2645 GtkToggleAction *toggle;
2646 ModestWindowPrivate *parent_priv;
2647 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2649 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2650 gtk_toggle_action_set_active (toggle, FALSE);
2655 update_paste_dimming (ModestMsgEditWindow *window)
2657 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2658 GtkAction *action = NULL;
2659 GtkClipboard *clipboard = NULL;
2661 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2663 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2664 gtk_action_set_sensitive (action, gtk_clipboard_wait_is_text_available (clipboard));
2669 modest_msg_edit_window_system_clipboard_owner_change (GtkClipboard *clipboard,
2671 ModestMsgEditWindow *window)
2673 update_paste_dimming (window);
2677 update_select_all_dimming (ModestMsgEditWindow *window)
2680 gboolean dimmed = FALSE;
2682 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2684 focused = gtk_window_get_focus (GTK_WINDOW (window));
2685 if (GTK_IS_ENTRY (focused)) {
2686 const gchar *current_text;
2687 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
2688 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
2689 } else if (GTK_IS_TEXT_VIEW (focused)) {
2690 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
2691 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
2692 } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
2695 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
2696 gtk_action_set_sensitive (action, !dimmed);
2700 edit_menu_activated (GtkAction *action,
2703 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2705 update_select_all_dimming (window);