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);
128 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
129 ModestMsgEditWindow *window);
130 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
131 ModestMsgEditWindow *window);
133 /* list my signals */
140 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
141 struct _ModestMsgEditWindowPrivate {
143 GtkWidget *header_box;
145 ModestPairList *from_field_protos;
146 GtkWidget *from_field;
150 GtkWidget *bcc_field;
151 GtkWidget *subject_field;
152 GtkWidget *attachments_view;
153 GtkWidget *priority_icon;
154 GtkWidget *add_attachment_button;
156 GtkWidget *cc_caption;
157 GtkWidget *bcc_caption;
158 GtkWidget *attachments_caption;
160 GtkTextBuffer *text_buffer;
162 GtkWidget *font_size_toolitem;
163 GtkWidget *font_face_toolitem;
164 GtkWidget *font_color_button;
165 GSList *font_items_group;
166 GtkWidget *font_tool_button_label;
167 GSList *size_items_group;
168 GtkWidget *size_tool_button_label;
170 GtkWidget *find_toolbar;
177 TnyHeaderFlags priority_flags;
181 gulong clipboard_change_handler_id;
182 gulong system_clipboard_change_handler_id;
187 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
188 MODEST_TYPE_MSG_EDIT_WINDOW, \
189 ModestMsgEditWindowPrivate))
191 static GtkWindowClass *parent_class = NULL;
193 /* uncomment the following if you have defined any signals */
194 /* static guint signals[LAST_SIGNAL] = {0}; */
197 modest_msg_edit_window_get_type (void)
199 static GType my_type = 0;
201 static const GTypeInfo my_info = {
202 sizeof(ModestMsgEditWindowClass),
203 NULL, /* base init */
204 NULL, /* base finalize */
205 (GClassInitFunc) modest_msg_edit_window_class_init,
206 NULL, /* class finalize */
207 NULL, /* class data */
208 sizeof(ModestMsgEditWindow),
210 (GInstanceInitFunc) modest_msg_edit_window_init,
213 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
214 "ModestMsgEditWindow",
217 wp_text_buffer_library_init ();
223 save_state (ModestWindow *self)
225 modest_widget_memory_save (modest_runtime_get_conf(),
226 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
231 restore_settings (ModestMsgEditWindow *self)
233 modest_widget_memory_restore (modest_runtime_get_conf(),
234 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
239 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
241 GObjectClass *gobject_class;
242 ModestWindowClass *modest_window_class;
243 gobject_class = (GObjectClass*) klass;
244 modest_window_class = (ModestWindowClass*) klass;
246 parent_class = g_type_class_peek_parent (klass);
247 gobject_class->finalize = modest_msg_edit_window_finalize;
249 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
250 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
251 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
252 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
253 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
255 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
257 modest_window_class->save_state_func = save_state;
261 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
263 ModestMsgEditWindowPrivate *priv;
264 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
266 priv->msg_body = NULL;
267 priv->from_field = NULL;
268 priv->to_field = NULL;
269 priv->cc_field = NULL;
270 priv->bcc_field = NULL;
271 priv->subject_field = NULL;
272 priv->attachments = NULL;
274 priv->zoom_level = 1.0;
276 priv->cc_caption = NULL;
277 priv->bcc_caption = NULL;
279 priv->priority_flags = 0;
281 priv->find_toolbar = NULL;
283 priv->draft_msg = NULL;
284 priv->clipboard_change_handler_id = 0;
285 priv->system_clipboard_change_handler_id = 0;
289 /* FIXME: this is a dup from the one in gtk/ */
292 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
294 static ModestPairList*
295 get_transports (void)
297 GSList *transports = NULL;
299 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
300 GSList *accounts = modest_account_mgr_account_names (account_mgr,
301 TRUE /* only enabled accounts. */);
303 GSList *cursor = accounts;
305 gchar *account_name = cursor->data;
306 gchar *from_string = NULL;
308 from_string = modest_account_mgr_get_from_string (account_mgr,
312 if (from_string && account_name) {
313 gchar *name = account_name;
314 ModestPair *pair = modest_pair_new ((gpointer) name,
315 (gpointer) from_string , TRUE);
316 transports = g_slist_prepend (transports, pair);
319 cursor = cursor->next;
321 g_slist_free (accounts); /* only free the accounts, not the elements,
322 * because they are used in the pairlist */
328 init_window (ModestMsgEditWindow *obj)
330 GtkWidget *from_caption, *to_caption, *subject_caption;
331 GtkWidget *main_vbox;
332 ModestMsgEditWindowPrivate *priv;
334 GtkSizeGroup *size_group;
336 GtkWidget *scroll_area;
337 GtkWidget *subject_box;
338 GtkWidget *attachment_icon;
339 GtkWidget *window_box;
341 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
343 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
345 /* Note: This ModestPairList* must exist for as long as the combo
346 * that uses it, because the ModestComboBox uses the ID opaquely,
347 * so it can't know how to manage its memory. */
348 priv->from_field_protos = get_transports ();
350 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
352 priv->to_field = modest_recpt_editor_new ();
353 priv->cc_field = modest_recpt_editor_new ();
354 priv->bcc_field = modest_recpt_editor_new ();
355 subject_box = gtk_hbox_new (FALSE, 0);
356 priv->priority_icon = gtk_image_new ();
357 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
358 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
359 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
360 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
361 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
362 priv->add_attachment_button = gtk_button_new ();
363 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
364 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
365 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
366 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
367 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
368 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
369 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
370 priv->attachments_view = modest_attachments_view_new (NULL);
372 priv->header_box = gtk_vbox_new (FALSE, 0);
374 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
375 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
376 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
377 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
378 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
379 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
380 g_object_unref (size_group);
382 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
383 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
384 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
385 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
386 gtk_size_group_add_widget (size_group, priv->subject_field);
387 gtk_size_group_add_widget (size_group, priv->attachments_view);
388 g_object_unref (size_group);
390 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
391 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
392 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
393 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
394 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
395 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
396 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
399 priv->msg_body = wp_text_view_new ();
400 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
401 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
402 g_object_set (priv->text_buffer, "font_scale", 1.0, NULL);
403 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
404 /* gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
405 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
407 priv->find_toolbar = hildon_find_toolbar_new (NULL);
408 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
410 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
411 G_CALLBACK (text_buffer_refresh_attributes), obj);
412 g_signal_connect (G_OBJECT (priv->text_buffer), "delete-range",
413 G_CALLBACK (text_buffer_delete_range), obj);
414 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
415 G_CALLBACK (text_buffer_can_undo), obj);
416 g_signal_connect (G_OBJECT (obj), "window-state-event",
417 G_CALLBACK (modest_msg_edit_window_window_state_event),
419 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
420 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
421 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
422 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
423 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
424 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
426 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
427 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
429 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
430 G_CALLBACK (msg_body_focus), obj);
431 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
432 G_CALLBACK (msg_body_focus), obj);
433 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
434 "changed", G_CALLBACK (recpt_field_changed), obj);
435 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
436 "changed", G_CALLBACK (recpt_field_changed), obj);
437 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
438 "changed", G_CALLBACK (recpt_field_changed), obj);
439 recpt_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
440 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
442 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
443 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
445 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
446 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
447 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
449 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
451 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
452 frame = gtk_frame_new (NULL);
453 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
455 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
456 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
457 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
459 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL)) {
460 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
461 gtk_widget_hide (priv->cc_caption);
463 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL)) {
464 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
465 gtk_widget_hide (priv->bcc_caption);
468 window_box = gtk_vbox_new (FALSE, 0);
469 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
470 gtk_box_pack_end (GTK_BOX (window_box), priv->find_toolbar, FALSE, FALSE, 0);
471 gtk_container_add (GTK_CONTAINER(obj), window_box);
472 scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
473 gtk_container_add (GTK_CONTAINER (frame), scroll_area);
474 gtk_container_set_focus_vadjustment (GTK_CONTAINER (scroll_area),
475 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
477 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
478 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
479 priv->system_clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
480 G_CALLBACK (modest_msg_edit_window_system_clipboard_owner_change), obj);
486 modest_msg_edit_window_finalize (GObject *obj)
488 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
490 if (priv->clipboard_change_handler_id > 0) {
491 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), priv->clipboard_change_handler_id);
492 priv->clipboard_change_handler_id = 0;
495 if (priv->system_clipboard_change_handler_id > 0) {
496 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
497 priv->system_clipboard_change_handler_id);
498 priv->system_clipboard_change_handler_id = 0;
501 /* This had to stay alive for as long as the combobox that used it: */
502 modest_pair_list_free (priv->from_field_protos);
504 G_OBJECT_CLASS(parent_class)->finalize (obj);
508 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMsgEditWindow *self)
510 GtkWidget *close_dialog;
511 ModestMsgEditWindowPrivate *priv;
514 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
515 modest_window_save_state (MODEST_WINDOW (self));
516 if (is_modified (self)) {
517 close_dialog = hildon_note_new_confirmation (GTK_WINDOW (self), _("mcen_nc_no_email_message_modified_save_changes"));
518 response = gtk_dialog_run (GTK_DIALOG (close_dialog));
519 gtk_widget_destroy (close_dialog);
521 if (response != GTK_RESPONSE_CANCEL) {
522 modest_ui_actions_on_save_to_drafts (NULL, self);
525 /* /\* remove old message from drafts *\/ */
526 /* if (priv->draft_msg) { */
527 /* TnyHeader *header = tny_msg_get_header (priv->draft_msg); */
528 /* TnyAccount *account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(), */
530 /* TNY_ACCOUNT_TYPE_STORE); */
531 /* TnyFolder *folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS); */
532 /* g_return_val_if_fail (TNY_IS_HEADER (header), FALSE); */
533 /* g_return_val_if_fail (TNY_IS_FOLDER (folder), FALSE); */
534 /* tny_folder_remove_msg (folder, header, NULL); */
535 /* g_object_unref (folder); */
536 /* g_object_unref (header); */
537 /* g_object_unref (priv->draft_msg); */
538 /* priv->draft_msg = NULL; */
540 gtk_widget_destroy (GTK_WIDGET (self));
546 menubar_to_menu (GtkUIManager *ui_manager)
548 GtkWidget *main_menu;
552 /* Create new main menu */
553 main_menu = gtk_menu_new();
555 /* Get the menubar from the UI manager */
556 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
558 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
562 menu = GTK_WIDGET (iter->data);
563 gtk_widget_reparent(menu, main_menu);
565 iter = g_list_next (iter);
572 set_msg (ModestMsgEditWindow *self, TnyMsg *msg)
575 const gchar *to, *cc, *bcc, *subject;
577 ModestMsgEditWindowPrivate *priv;
579 TnyHeaderFlags priority_flags;
581 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
582 g_return_if_fail (TNY_IS_MSG (msg));
584 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
586 header = tny_msg_get_header (msg);
587 to = tny_header_get_to (header);
588 cc = tny_header_get_cc (header);
589 bcc = tny_header_get_bcc (header);
590 subject = tny_header_get_subject (header);
591 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
594 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
596 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
598 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
600 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
601 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
604 update_window_title (self);
606 /* gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
607 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
608 body = modest_tny_msg_get_body (msg, TRUE);
610 if ((body == NULL)||(body[0] == '\0')) {
612 body = modest_text_utils_convert_to_html ("");
614 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
615 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
618 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
621 /* Get the default format required from configuration */
622 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
623 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
626 /* Set the default focus depending on having already a To: field or not */
627 if ((!to)||(*to == '\0')) {
628 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
630 gtk_widget_grab_focus (priv->msg_body);
633 /* TODO: lower priority, select in the From: combo to the
634 value that comes from msg <- not sure, should it be
637 /* Add attachments to the view */
638 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
639 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
640 if (priv->attachments == NULL) {
641 gtk_widget_hide (priv->attachments_caption);
643 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
644 gtk_widget_show_all (priv->attachments_caption);
647 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
648 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
650 reset_modified (self);
652 update_dimmed (self);
653 text_buffer_can_undo (priv->text_buffer, FALSE, self);
655 priv->draft_msg = msg;
659 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
662 GList *item_children, *node;
663 GtkWidget *bin_child;
665 bin_child = gtk_bin_get_child (GTK_BIN(item));
667 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
669 for (node = item_children; node != NULL; node = g_list_next (node)) {
670 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
671 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
674 g_list_free (item_children);
678 menu_tool_button_dont_expand (GtkMenuToolButton *item)
681 GList *item_children, *node;
683 box = gtk_bin_get_child (GTK_BIN (item));
684 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
685 item_children = gtk_container_get_children (GTK_CONTAINER (box));
687 for (node = item_children; node != NULL; node = g_list_next (node)) {
688 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
689 if (GTK_IS_TOGGLE_BUTTON (node->data))
690 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
691 else if (GTK_IS_BUTTON (node->data))
692 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
694 g_list_free (item_children);
699 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
701 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
702 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
703 GtkWidget *placeholder;
704 GtkWidget *tool_item;
709 GtkWidget *sizes_menu;
710 GtkWidget *fonts_menu;
711 GSList *radio_group = NULL;
716 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
717 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
719 /* should we hide the toolbar? */
720 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
721 gtk_widget_hide (parent_priv->toolbar);
723 /* Font color placeholder */
724 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
725 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
728 tool_item = GTK_WIDGET (gtk_tool_item_new ());
729 priv->font_color_button = hildon_color_button_new ();
730 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
731 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
732 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
733 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
734 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
735 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
736 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
738 /* Font size and face placeholder */
739 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
740 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
742 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
743 priv->size_tool_button_label = gtk_label_new (NULL);
744 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
745 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
746 size_text,"</span>", NULL);
747 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
749 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
750 sizes_menu = gtk_menu_new ();
751 priv->size_items_group = NULL;
753 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
754 GtkWidget *size_menu_item;
756 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
757 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
758 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
759 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
760 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
761 gtk_widget_show (size_menu_item);
763 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
767 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
768 GtkWidget *item = (GtkWidget *) node->data;
769 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
773 priv->size_items_group = g_slist_reverse (priv->size_items_group);
774 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
775 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
776 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
777 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
778 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
779 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
780 priv->font_size_toolitem = tool_item;
783 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
784 priv->font_tool_button_label = gtk_label_new (NULL);
785 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
786 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
788 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
789 fonts_menu = gtk_menu_new ();
790 priv->font_items_group = NULL;
792 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
793 GtkWidget *font_menu_item;
794 GtkWidget *child_label;
796 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
797 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
798 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
799 wp_get_font_name (font_index), "</span>", NULL);
800 gtk_label_set_markup (GTK_LABEL (child_label), markup);
803 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
804 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
805 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
806 gtk_widget_show (font_menu_item);
808 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
811 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
812 GtkWidget *item = (GtkWidget *) node->data;
813 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
816 priv->font_items_group = g_slist_reverse (priv->font_items_group);
817 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
818 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
819 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
820 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
821 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
822 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
823 priv->font_face_toolitem = tool_item;
825 /* Set expand and homogeneous for remaining items */
826 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
827 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
828 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
829 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
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/ActionsItalics");
833 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
834 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
842 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name)
845 ModestWindowPrivate *parent_priv;
846 ModestMsgEditWindowPrivate *priv;
847 GtkActionGroup *action_group;
848 GError *error = NULL;
849 GdkPixbuf *window_icon = NULL;
852 gboolean prefer_formatted;
854 ModestPair *account_pair = NULL;
856 g_return_val_if_fail (msg, NULL);
857 g_return_val_if_fail (account_name, NULL);
859 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
861 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
862 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
864 parent_priv->ui_manager = gtk_ui_manager_new();
865 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
866 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
868 /* Add common actions */
869 gtk_action_group_add_actions (action_group,
870 modest_msg_edit_action_entries,
871 G_N_ELEMENTS (modest_msg_edit_action_entries),
873 gtk_action_group_add_toggle_actions (action_group,
874 modest_msg_edit_toggle_action_entries,
875 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
877 gtk_action_group_add_radio_actions (action_group,
878 modest_msg_edit_alignment_radio_action_entries,
879 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
881 G_CALLBACK (modest_ui_actions_on_change_justify),
883 gtk_action_group_add_radio_actions (action_group,
884 modest_msg_edit_zoom_action_entries,
885 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
887 G_CALLBACK (modest_ui_actions_on_change_zoom),
889 gtk_action_group_add_radio_actions (action_group,
890 modest_msg_edit_priority_action_entries,
891 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
893 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
895 gtk_action_group_add_radio_actions (action_group,
896 modest_msg_edit_file_format_action_entries,
897 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
898 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
899 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
901 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
902 g_object_unref (action_group);
904 /* Load the UI definition */
905 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
908 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
909 g_clear_error (&error);
912 /* Add accelerators */
913 gtk_window_add_accel_group (GTK_WINDOW (obj),
914 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
917 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
918 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
921 init_window (MODEST_MSG_EDIT_WINDOW(obj));
923 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
925 gtk_window_set_icon_from_file (GTK_WINDOW(obj), MODEST_APP_ICON, NULL);
927 g_signal_connect (G_OBJECT(obj), "delete-event",
928 G_CALLBACK(on_delete_event), obj);
930 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
932 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
934 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
936 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
937 if (account_pair != NULL)
938 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
940 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg);
942 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
944 /* Set window icon */
945 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
946 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
948 /* Dim at start clipboard actions */
949 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
950 gtk_action_set_sensitive (action, FALSE);
951 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
952 gtk_action_set_sensitive (action, FALSE);
953 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
954 gtk_action_set_sensitive (action, FALSE);
956 /* set initial state of cc and bcc */
957 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
958 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
959 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
960 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
961 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
962 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
964 /* Setup the file format */
965 conf = modest_runtime_get_conf ();
966 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
968 g_clear_error (&error);
969 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
971 file_format = (prefer_formatted) ?
972 MODEST_FILE_FORMAT_FORMATTED_TEXT :
973 MODEST_FILE_FORMAT_PLAIN_TEXT;
974 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
976 update_paste_dimming (MODEST_MSG_EDIT_WINDOW (obj));
978 return (ModestWindow*) obj;
982 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
984 GString **string_buffer = (GString **) user_data;
986 *string_buffer = g_string_append (*string_buffer, buffer);
992 * @result: A new string which should be freed with g_free().
995 get_formatted_data (ModestMsgEditWindow *edit_window)
997 ModestMsgEditWindowPrivate *priv;
998 GString *string_buffer = g_string_new ("");
1000 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1002 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1004 return g_string_free (string_buffer, FALSE);
1009 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1012 const gchar *account_name;
1013 ModestMsgEditWindowPrivate *priv;
1015 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1017 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1019 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1020 g_return_val_if_fail (account_name, NULL);
1023 /* don't free these (except from) */
1024 data = g_slice_new0 (MsgData);
1025 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1027 data->account_name = g_strdup (account_name);
1028 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1029 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1030 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1031 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1032 if (priv->draft_msg) {
1033 data->draft_msg = g_object_ref (priv->draft_msg);
1035 data->draft_msg = NULL;
1038 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1040 gtk_text_buffer_get_bounds (buf, &b, &e);
1041 data->plain_body = g_strdup (gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE)); /* returns a copy */
1043 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1044 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1046 data->html_body = NULL;
1048 data->attachments = priv->attachments; /* TODO: copy and free ? */
1049 data->priority_flags = priv->priority_flags;
1054 /* TODO: We must duplicate this implementation for GNOME and Maemo, but that is unwise. */
1056 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1059 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1067 g_free (data->subject);
1068 g_free (data->plain_body);
1069 g_free (data->html_body);
1070 if (data->draft_msg != NULL) {
1071 g_object_unref (data->draft_msg);
1072 data->draft_msg = NULL;
1074 g_free (data->account_name);
1076 /* TODO: Free data->attachments? */
1078 g_slice_free (MsgData, data);
1082 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1085 ModestMsgEditWindowPrivate *priv = NULL;
1086 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1088 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1090 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1092 return MODEST_MSG_EDIT_FORMAT_HTML;
1094 return MODEST_MSG_EDIT_FORMAT_TEXT;
1098 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1099 ModestMsgEditFormat format)
1101 ModestMsgEditWindowPrivate *priv;
1103 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1104 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1107 case MODEST_MSG_EDIT_FORMAT_HTML:
1108 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1110 case MODEST_MSG_EDIT_FORMAT_TEXT:
1111 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1114 g_return_if_reached ();
1118 ModestMsgEditFormatState *
1119 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1121 ModestMsgEditFormatState *format_state = NULL;
1122 ModestMsgEditWindowPrivate *priv;
1123 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1125 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1126 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1128 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1130 format_state = g_new0 (ModestMsgEditFormatState, 1);
1131 format_state->bold = buffer_format->bold&0x1;
1132 format_state->italics = buffer_format->italic&0x1;
1133 format_state->bullet = buffer_format->bullet&0x1;
1134 format_state->color = buffer_format->color;
1135 format_state->font_size = buffer_format->font_size;
1136 format_state->font_family = wp_get_font_name (buffer_format->font);
1137 format_state->justification = buffer_format->justification;
1138 g_free (buffer_format);
1140 return format_state;
1145 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1146 const ModestMsgEditFormatState *format_state)
1148 ModestMsgEditWindowPrivate *priv;
1149 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1150 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1151 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1152 g_return_if_fail (format_state != NULL);
1154 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1155 gtk_widget_grab_focus (priv->msg_body);
1156 buffer_format->bold = (format_state->bold != FALSE);
1157 buffer_format->italic = (format_state->italics != FALSE);
1158 buffer_format->color = format_state->color;
1159 buffer_format->font_size = format_state->font_size;
1160 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1161 buffer_format->justification = format_state->justification;
1162 buffer_format->bullet = format_state->bullet;
1164 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1166 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1167 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1168 buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
1169 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1170 buffer_format->cs.font = (buffer_format->font != current_format->font);
1171 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1172 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1174 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1175 if (buffer_format->cs.bold) {
1176 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1178 if (buffer_format->cs.italic) {
1179 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1181 if (buffer_format->cs.color) {
1182 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1184 if (buffer_format->cs.font_size) {
1185 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->font_size));
1187 if (buffer_format->cs.justification) {
1188 switch (buffer_format->justification) {
1189 case GTK_JUSTIFY_LEFT:
1190 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1192 case GTK_JUSTIFY_CENTER:
1193 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1195 case GTK_JUSTIFY_RIGHT:
1196 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1203 if (buffer_format->cs.font) {
1204 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->font));
1206 if (buffer_format->cs.bullet) {
1207 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((int)buffer_format->bullet));
1209 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1210 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1212 g_free (current_format);
1217 toggle_action_set_active_block_notify (GtkToggleAction *action,
1220 GSList *proxies = NULL;
1222 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1223 proxies != NULL; proxies = g_slist_next (proxies)) {
1224 GtkWidget *widget = (GtkWidget *) proxies->data;
1225 gtk_action_block_activate_from (GTK_ACTION (action), widget);
1228 gtk_toggle_action_set_active (action, value);
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_unblock_activate_from (GTK_ACTION (action), widget);
1238 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1240 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1242 ModestWindowPrivate *parent_priv;
1243 ModestMsgEditWindowPrivate *priv;
1244 GtkWidget *new_size_menuitem;
1245 GtkWidget *new_font_menuitem;
1247 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1248 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1250 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1251 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1252 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1253 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1255 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1256 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1257 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1260 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1262 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1263 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1265 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1266 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1268 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1269 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1271 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1272 G_CALLBACK (modest_msg_edit_window_color_button_change),
1274 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1275 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1276 G_CALLBACK (modest_msg_edit_window_color_button_change),
1279 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1280 buffer_format->font_size))->data);
1281 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1285 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1286 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1287 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1289 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1290 G_CALLBACK (modest_msg_edit_window_size_change),
1292 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1293 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1294 G_CALLBACK (modest_msg_edit_window_size_change),
1298 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1299 buffer_format->font))->data);
1300 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1304 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1305 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1306 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1308 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1309 G_CALLBACK (modest_msg_edit_window_font_change),
1311 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1312 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1313 G_CALLBACK (modest_msg_edit_window_font_change),
1317 g_free (buffer_format);
1323 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1326 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1327 ModestMsgEditWindowPrivate *priv;
1328 GtkWidget *dialog = NULL;
1330 const GdkColor *new_color = NULL;
1332 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1333 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1335 #ifdef MODEST_HILDON_VERSION_0
1336 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1337 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1339 dialog = hildon_color_chooser_new ();
1340 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1341 #endif /*MODEST_HILDON_VERSION_0*/
1342 g_free (buffer_format);
1344 response = gtk_dialog_run (GTK_DIALOG (dialog));
1346 case GTK_RESPONSE_OK: {
1347 #ifdef MODEST_HILDON_VERSION_0
1348 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1351 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1353 #endif /*MODEST_HILDON_VERSION_0*/
1360 gtk_widget_destroy (dialog);
1362 if (new_color != NULL)
1363 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1368 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1371 ModestMsgEditWindowPrivate *priv;
1372 GtkWidget *dialog = NULL;
1374 GdkColor *old_color = NULL;
1375 const GdkColor *new_color = NULL;
1377 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1378 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1380 #ifdef MODEST_HILDON_VERSION_0
1381 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1382 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1384 dialog = hildon_color_chooser_new ();
1385 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1386 #endif /*MODEST_HILDON_VERSION_9*/
1388 response = gtk_dialog_run (GTK_DIALOG (dialog));
1390 case GTK_RESPONSE_OK: {
1391 #ifdef MODEST_HILDON_VERSION_0
1392 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1395 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1397 #endif /*MODEST_HILDON_VERSION_0*/
1403 gtk_widget_destroy (dialog);
1405 if (new_color != NULL)
1406 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1411 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1414 ModestMsgEditWindowPrivate *priv;
1415 GtkWidget *dialog = NULL;
1417 gchar *filename = NULL;
1419 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1421 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1422 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1424 response = gtk_dialog_run (GTK_DIALOG (dialog));
1426 case GTK_RESPONSE_OK:
1427 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1432 gtk_widget_destroy (dialog);
1435 GdkPixbuf *pixbuf = NULL;
1436 GtkTextIter position;
1437 GtkTextMark *insert_mark;
1439 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
1442 GdkPixbufFormat *pixbuf_format;
1444 image_file_id = g_open (filename, O_RDONLY, 0);
1445 pixbuf_format = gdk_pixbuf_get_file_info (filename, NULL, NULL);
1446 if ((image_file_id != -1)&&(pixbuf_format != NULL)) {
1447 TnyMimePart *image_part;
1448 TnyStream *image_stream;
1454 mime_types = gdk_pixbuf_format_get_mime_types (pixbuf_format);
1455 if ((mime_types != NULL) && (mime_types[0] != NULL)) {
1456 mime_type = mime_types[0];
1458 mime_type = "image/unknown";
1460 image_part = tny_platform_factory_new_mime_part
1461 (modest_runtime_get_platform_factory ());
1462 image_stream = TNY_STREAM (tny_fs_stream_new (image_file_id));
1464 tny_mime_part_construct_from_stream (image_part, image_stream, mime_type);
1465 g_strfreev (mime_types);
1467 content_id = g_strdup_printf ("%d", priv->last_cid);
1468 tny_mime_part_set_content_id (image_part, content_id);
1469 g_free (content_id);
1472 basename = g_path_get_basename (filename);
1473 tny_mime_part_set_filename (image_part, basename);
1476 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1477 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1478 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (image_part)), pixbuf);
1479 priv->attachments = g_list_prepend (priv->attachments, image_part);
1480 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1482 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1483 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1484 gtk_widget_show_all (priv->attachments_caption);
1485 } else if (image_file_id == -1) {
1486 close (image_file_id);
1495 modest_msg_edit_window_attach_file (ModestMsgEditWindow *window)
1498 ModestMsgEditWindowPrivate *priv;
1499 GtkWidget *dialog = NULL;
1501 GSList *uris = NULL;
1504 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1506 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1507 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1509 response = gtk_dialog_run (GTK_DIALOG (dialog));
1511 case GTK_RESPONSE_OK:
1512 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1517 gtk_widget_destroy (dialog);
1519 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1521 GnomeVFSHandle *handle = NULL;
1522 GnomeVFSResult result;
1524 uri = (const gchar *) uri_node->data;
1525 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1526 if (result == GNOME_VFS_OK) {
1527 TnyMimePart *mime_part;
1529 const gchar *mime_type = NULL;
1533 GnomeVFSFileInfo info;
1535 filename = g_filename_from_uri (uri, NULL, NULL);
1537 if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE) == GNOME_VFS_OK)
1538 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1539 mime_part = tny_platform_factory_new_mime_part
1540 (modest_runtime_get_platform_factory ());
1541 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1543 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1545 content_id = g_strdup_printf ("%d", priv->last_cid);
1546 tny_mime_part_set_content_id (mime_part, content_id);
1547 g_free (content_id);
1550 basename = g_path_get_basename (filename);
1551 tny_mime_part_set_filename (mime_part, basename);
1554 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1555 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1557 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1558 gtk_widget_show_all (priv->attachments_caption);
1559 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1564 g_slist_foreach (uris, (GFunc) g_free, NULL);
1565 g_slist_free (uris);
1569 modest_msg_edit_window_attach_file_noninteractive (
1570 ModestMsgEditWindow *window,
1571 const gchar *file_uri)
1574 ModestMsgEditWindowPrivate *priv;
1576 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1581 /* TODO: We should probably try to use only the URI,
1582 * instead of using a filename.
1584 gchar* filename = g_filename_from_uri (file_uri, NULL, NULL);
1586 g_warning("%s: g_filename_from_uri(%s) failed.\n", __FUNCTION__, file_uri);
1589 file_id = g_open (filename, O_RDONLY, 0);
1590 if (file_id != -1) {
1591 TnyMimePart *mime_part;
1593 const gchar *mime_type;
1597 mime_type = gnome_vfs_get_file_mime_type_fast (filename, NULL);
1598 mime_part = tny_platform_factory_new_mime_part
1599 (modest_runtime_get_platform_factory ());
1600 stream = TNY_STREAM (tny_fs_stream_new (file_id));
1602 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1604 content_id = g_strdup_printf ("%d", priv->last_cid);
1605 tny_mime_part_set_content_id (mime_part, content_id);
1606 g_free (content_id);
1609 basename = g_path_get_basename (filename);
1610 tny_mime_part_set_filename (mime_part, basename);
1613 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1614 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1616 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1617 gtk_widget_show_all (priv->attachments_caption);
1618 } else if (file_id == -1) {
1620 g_warning("file to be attached does not exist: %s", filename);
1628 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1631 ModestMsgEditWindowPrivate *priv;
1632 gboolean clean_list = FALSE;
1634 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1635 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1637 if (att_list == NULL) {
1638 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1642 if (att_list == NULL) {
1643 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1645 GtkWidget *confirmation_dialog = NULL;
1646 gboolean dialog_response;
1648 gchar *message = NULL;
1649 const gchar *filename = NULL;
1651 if (att_list->next == NULL) {
1652 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1656 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1657 att_list->next == NULL), filename);
1658 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1660 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1661 gtk_widget_destroy (confirmation_dialog);
1662 if (!dialog_response) {
1664 g_list_free (att_list);
1667 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1669 for (node = att_list; node != NULL; node = g_list_next (node)) {
1670 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1671 const gchar *att_id;
1672 priv->attachments = g_list_remove (priv->attachments, mime_part);
1674 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1676 if (priv->attachments == NULL)
1677 gtk_widget_hide (priv->attachments_caption);
1678 att_id = tny_mime_part_get_content_id (mime_part);
1680 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1682 g_object_unref (mime_part);
1683 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1688 g_list_free (att_list);
1692 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1695 ModestMsgEditWindowPrivate *priv;
1696 GdkColor *new_color;
1697 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1699 #ifdef MODEST_HILDON_VERSION_0
1700 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1703 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1705 #endif /*MODEST_HILDON_VERSION_0*/
1707 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1709 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1714 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1717 ModestMsgEditWindowPrivate *priv;
1718 gint new_size_index;
1719 ModestMsgEditWindow *window;
1722 window = MODEST_MSG_EDIT_WINDOW (userdata);
1723 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1724 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1726 if (gtk_check_menu_item_get_active (menu_item)) {
1728 WPTextBufferFormat format;
1730 memset (&format, 0, sizeof (format));
1731 wp_text_buffer_get_current_state (WP_TEXT_BUFFER (priv->text_buffer), &format);
1733 label = gtk_bin_get_child (GTK_BIN (menu_item));
1735 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1736 format.cs.font_size = TRUE;
1737 format.cs.text_position = TRUE;
1738 format.cs.font = TRUE;
1739 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1740 wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format);
1742 /* if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, */
1743 /* (gpointer) wp_get_font_size_index (new_size_index, 12))) */
1744 /* wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body)); */
1746 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1747 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1748 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1754 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1757 ModestMsgEditWindowPrivate *priv;
1758 gint new_font_index;
1759 ModestMsgEditWindow *window;
1762 window = MODEST_MSG_EDIT_WINDOW (userdata);
1763 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1764 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1766 if (gtk_check_menu_item_get_active (menu_item)) {
1769 label = gtk_bin_get_child (GTK_BIN (menu_item));
1771 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1773 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1774 (gpointer) new_font_index))
1775 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1777 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1778 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1779 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1785 modest_msg_edit_window_set_zoom (ModestWindow *window,
1788 ModestMsgEditWindowPrivate *priv;
1790 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1792 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1793 priv->zoom_level = zoom;
1794 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom);
1798 modest_msg_edit_window_get_zoom (ModestWindow *window)
1800 ModestMsgEditWindowPrivate *priv;
1802 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1804 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1805 return priv->zoom_level;
1809 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1811 ModestWindowPrivate *parent_priv;
1812 GtkRadioAction *zoom_radio_action;
1813 GSList *group, *node;
1815 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1816 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1817 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1819 group = gtk_radio_action_get_group (zoom_radio_action);
1821 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1822 hildon_banner_show_information (NULL, NULL, _("ckct_ib_max_zoom_level_reached"));
1826 for (node = group; node != NULL; node = g_slist_next (node)) {
1827 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1828 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1836 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1838 ModestWindowPrivate *parent_priv;
1839 GtkRadioAction *zoom_radio_action;
1840 GSList *group, *node;
1842 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1843 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1844 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1846 group = gtk_radio_action_get_group (zoom_radio_action);
1848 for (node = group; node != NULL; node = g_slist_next (node)) {
1849 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1850 if (node->next != NULL) {
1851 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1854 hildon_banner_show_information (NULL, NULL, _("ckct_ib_min_zoom_level_reached"));
1862 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1864 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1865 ModestWindowPrivate *parent_priv;
1866 ModestWindowMgr *mgr;
1867 gboolean is_fullscreen;
1868 GtkAction *fs_toggle_action;
1871 mgr = modest_runtime_get_window_mgr ();
1872 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1874 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1876 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1877 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1878 if (is_fullscreen != active)
1879 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1887 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
1889 ModestWindowPrivate *parent_priv;
1890 GtkAction *fs_toggle_action;
1893 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1895 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1896 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
1897 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
1901 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
1904 ModestMsgEditWindowPrivate *priv = NULL;
1905 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1907 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1908 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1910 gtk_widget_show (priv->cc_caption);
1912 gtk_widget_hide (priv->cc_caption);
1913 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
1917 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
1920 ModestMsgEditWindowPrivate *priv = NULL;
1921 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1923 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1924 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1926 gtk_widget_show (priv->bcc_caption);
1928 gtk_widget_hide (priv->bcc_caption);
1929 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
1933 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
1934 ModestRecptEditor *editor)
1936 ModestMsgEditWindowPrivate *priv;
1938 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1939 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
1940 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1942 if (editor == NULL) {
1943 GtkWidget *view_focus;
1944 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
1946 /* This code should be kept in sync with ModestRecptEditor. The
1947 textview inside the recpt editor is the one that really gets the
1948 focus. As it's inside a scrolled window, and this one inside the
1949 hbox recpt editor inherits from, we'll need to go up in the
1950 hierarchy to know if the text view is part of the recpt editor
1951 or if it's a different text entry */
1953 if (gtk_widget_get_parent (view_focus)) {
1954 GtkWidget *first_parent;
1956 first_parent = gtk_widget_get_parent (view_focus);
1957 if (gtk_widget_get_parent (first_parent) &&
1958 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
1959 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
1964 editor = MODEST_RECPT_EDITOR (priv->to_field);
1968 modest_address_book_select_addresses (editor);
1973 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
1975 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1977 modest_msg_edit_window_open_addressbook (window, NULL);
1981 modest_msg_edit_window_show_toolbar (ModestWindow *self,
1982 gboolean show_toolbar)
1984 ModestWindowPrivate *parent_priv;
1986 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1987 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1989 /* FIXME: we can not just use the code of
1990 modest_msg_edit_window_setup_toolbar because it has a
1991 mixture of both initialization and creation code. */
1994 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1996 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2000 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2001 TnyHeaderFlags priority_flags)
2003 ModestMsgEditWindowPrivate *priv;
2004 ModestWindowPrivate *parent_priv;
2006 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2008 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2009 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2010 priority_flags = priority_flags & (TNY_HEADER_FLAG_HIGH_PRIORITY);
2012 if (priv->priority_flags != priority_flags) {
2013 GtkAction *priority_action = NULL;
2015 priv->priority_flags = priority_flags;
2017 switch (priority_flags) {
2018 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2019 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2020 gtk_widget_show (priv->priority_icon);
2021 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2022 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2024 case TNY_HEADER_FLAG_LOW_PRIORITY:
2025 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2026 gtk_widget_show (priv->priority_icon);
2027 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2028 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2031 gtk_widget_hide (priv->priority_icon);
2032 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2033 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2036 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2037 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2042 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2045 ModestMsgEditWindowPrivate *priv;
2046 gint current_format;
2048 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2050 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2052 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2053 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2055 if (current_format != file_format) {
2056 switch (file_format) {
2057 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2058 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2060 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2064 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2065 response = gtk_dialog_run (GTK_DIALOG (dialog));
2066 gtk_widget_destroy (dialog);
2067 if (response == GTK_RESPONSE_OK)
2068 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2072 update_dimmed (window);
2077 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2080 ModestMsgEditWindowPrivate *priv;
2081 WPTextBufferFormat oldfmt, fmt;
2082 gint old_position = 0;
2086 GdkColor *color = NULL;
2087 gboolean bold, bold_set, italic, italic_set;
2088 gboolean underline, underline_set;
2089 gboolean strikethrough, strikethrough_set;
2090 gboolean position_set;
2091 gboolean font_size_set, font_set, color_set;
2094 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2095 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2097 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2099 /* First we get the currently selected font information */
2100 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2101 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2103 switch (oldfmt.text_position) {
2104 case TEXT_POSITION_NORMAL:
2107 case TEXT_POSITION_SUPERSCRIPT:
2115 g_object_set (G_OBJECT (dialog),
2116 "bold", oldfmt.bold != FALSE,
2117 "bold-set", !oldfmt.cs.bold,
2118 "underline", oldfmt.underline != FALSE,
2119 "underline-set", !oldfmt.cs.underline,
2120 "italic", oldfmt.italic != FALSE,
2121 "italic-set", !oldfmt.cs.italic,
2122 "strikethrough", oldfmt.strikethrough != FALSE,
2123 "strikethrough-set", !oldfmt.cs.strikethrough,
2124 "color", &oldfmt.color,
2125 "color-set", !oldfmt.cs.color,
2126 "size", wp_font_size[oldfmt.font_size],
2127 "size-set", !oldfmt.cs.font_size,
2128 "position", old_position,
2129 "position-set", !oldfmt.cs.text_position,
2130 "family", wp_get_font_name (oldfmt.font),
2131 "family-set", !oldfmt.cs.font,
2134 gtk_widget_show_all (dialog);
2135 response = gtk_dialog_run (GTK_DIALOG (dialog));
2136 if (response == GTK_RESPONSE_OK) {
2138 g_object_get( dialog,
2140 "bold-set", &bold_set,
2141 "underline", &underline,
2142 "underline-set", &underline_set,
2144 "italic-set", &italic_set,
2145 "strikethrough", &strikethrough,
2146 "strikethrough-set", &strikethrough_set,
2148 "color-set", &color_set,
2150 "size-set", &font_size_set,
2151 "family", &font_name,
2152 "family-set", &font_set,
2153 "position", &position,
2154 "position-set", &position_set,
2159 if (response == GTK_RESPONSE_OK) {
2160 memset(&fmt, 0, sizeof(fmt));
2166 fmt.italic = italic;
2167 fmt.cs.italic = TRUE;
2169 if (underline_set) {
2170 fmt.underline = underline;
2171 fmt.cs.underline = TRUE;
2173 if (strikethrough_set) {
2174 fmt.strikethrough = strikethrough;
2175 fmt.cs.strikethrough = TRUE;
2180 ? TEXT_POSITION_NORMAL
2181 : ( ( position == 1 )
2182 ? TEXT_POSITION_SUPERSCRIPT
2183 : TEXT_POSITION_SUBSCRIPT );
2184 fmt.cs.text_position = TRUE;
2188 fmt.cs.color = TRUE;
2191 fmt.font = wp_get_font_index(font_name,
2196 if (font_size_set) {
2197 fmt.font_size = wp_get_font_size_index(
2198 font_size, DEFAULT_FONT_SIZE);
2199 fmt.cs.font_size = TRUE;
2201 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2203 gtk_widget_destroy (dialog);
2205 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2209 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2211 ModestMsgEditWindowPrivate *priv;
2213 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2214 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2216 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2218 update_dimmed (window);
2223 update_dimmed (ModestMsgEditWindow *window)
2225 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2226 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2230 gboolean editor_focused;
2232 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2233 editor_focused = gtk_widget_is_focus (priv->msg_body);
2235 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2236 gtk_action_set_sensitive (action, rich_text && editor_focused);
2237 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2238 gtk_action_set_sensitive (action, rich_text && editor_focused);
2239 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2240 gtk_action_set_sensitive (action, rich_text && editor_focused);
2241 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2242 gtk_action_set_sensitive (action, rich_text && editor_focused);
2243 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2244 gtk_action_set_sensitive (action, rich_text && editor_focused);
2245 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2246 gtk_action_set_sensitive (action, rich_text && editor_focused);
2247 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2248 gtk_action_set_sensitive (action, rich_text && editor_focused);
2249 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2250 gtk_action_set_sensitive (action, rich_text && editor_focused);
2251 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2252 gtk_action_set_sensitive (action, rich_text && editor_focused);
2253 widget = priv->font_color_button;
2254 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2255 widget = priv->font_size_toolitem;
2256 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2257 widget = priv->font_face_toolitem;
2258 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2262 setup_insensitive_handlers (ModestMsgEditWindow *window)
2264 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2265 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2268 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2269 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2270 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2271 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2273 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2274 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2275 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2276 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2277 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2278 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2279 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2280 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2281 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
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/AlignmentMenu/AlignmentRightMenu");
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/AttachmentsMenu/InsertImageMenu");
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, "/ToolBar/ActionsBold");
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, "/ToolBar/ActionsItalics");
2290 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2291 widget = priv->font_color_button;
2292 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2293 widget = priv->font_size_toolitem;
2294 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2295 widget = priv->font_face_toolitem;
2296 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2298 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2299 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (remove_attachment_insensitive_press), window);
2303 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2305 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2308 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2309 gtk_action_set_sensitive (action, can_undo);
2313 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2316 GtkTextIter match_start, match_end;
2318 if (image_id == NULL)
2321 gtk_text_buffer_get_start_iter (buffer, &iter);
2323 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2324 GSList *tags = gtk_text_iter_get_tags (&match_start);
2326 for (node = tags; node != NULL; node = g_slist_next (node)) {
2327 GtkTextTag *tag = (GtkTextTag *) node->data;
2328 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2329 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2330 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2332 offset = gtk_text_iter_get_offset (&match_start);
2333 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2334 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2338 gtk_text_iter_forward_char (&iter);
2343 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2345 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2346 GtkTextIter real_start, real_end;
2347 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2349 if (gtk_text_iter_compare (start, end) > 0) {
2353 real_start = *start;
2357 GSList *tags = gtk_text_iter_get_tags (&real_start);
2359 for (node = tags; node != NULL; node = g_slist_next (node)) {
2360 GtkTextTag *tag = (GtkTextTag *) node->data;
2361 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2362 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2364 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2366 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2369 } while (gtk_text_iter_forward_char (&real_start)&&
2370 (gtk_text_iter_compare (&real_start, &real_end)<=0));
2374 msg_body_focus (GtkWidget *focus,
2375 GdkEventFocus *event,
2379 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2384 recpt_field_changed (GtkTextBuffer *buffer,
2385 ModestMsgEditWindow *editor)
2387 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2388 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2389 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2390 gboolean dim = FALSE;
2393 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2394 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2395 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2397 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2398 gtk_text_buffer_get_char_count (cc_buffer) +
2399 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2401 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2402 gtk_action_set_sensitive (action, !dim);
2403 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2404 gtk_action_set_sensitive (action, !dim);
2408 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2410 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2414 remove_attachment_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2416 ModestWindowPrivate *parent_priv;
2417 ModestMsgEditWindowPrivate *priv;
2418 GList *selected_attachments = NULL;
2419 gint n_att_selected = 0;
2421 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2422 parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2424 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2425 n_att_selected = g_list_length (selected_attachments);
2426 g_list_free (selected_attachments);
2428 if (n_att_selected > 1)
2429 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unable_to_display_more"));
2430 else if (n_att_selected == 0)
2431 hildon_banner_show_information (NULL, NULL, _("TODO: select one attachment"));
2436 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2438 gboolean rich_text, editor_focused;
2440 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2441 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2442 editor_focused = gtk_widget_is_focus (priv->msg_body);
2445 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2446 else if (!editor_focused)
2447 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2451 reset_modified (ModestMsgEditWindow *editor)
2453 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2454 GtkTextBuffer *buffer;
2456 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2457 gtk_text_buffer_set_modified (buffer, FALSE);
2458 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2459 gtk_text_buffer_set_modified (buffer, FALSE);
2460 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2461 gtk_text_buffer_set_modified (buffer, FALSE);
2462 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2466 is_modified (ModestMsgEditWindow *editor)
2468 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2469 GtkTextBuffer *buffer;
2471 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2472 if (gtk_text_buffer_get_modified (buffer))
2474 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2475 if (gtk_text_buffer_get_modified (buffer))
2477 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2478 if (gtk_text_buffer_get_modified (buffer))
2480 if (gtk_text_buffer_get_modified (priv->text_buffer))
2487 modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
2489 ModestMsgEditWindowPrivate *priv = NULL;
2491 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2492 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2494 /* check if there's no recipient added */
2495 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2496 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2497 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2498 /* no recipient contents, then select contacts */
2499 modest_msg_edit_window_open_addressbook (window, NULL);
2503 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
2505 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
2507 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
2510 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2517 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2518 ModestMsgEditWindow *window)
2520 modest_msg_edit_window_attach_file (window);
2524 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2526 ModestMsgEditWindow *window)
2528 ModestWindowPrivate *parent_priv;
2529 ModestMsgEditWindowPrivate *priv;
2533 GList *selected_attachments = NULL;
2534 gint n_att_selected = 0;
2536 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2537 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2538 selection = gtk_clipboard_wait_for_text (clipboard);
2539 focused = gtk_window_get_focus (GTK_WINDOW (window));
2541 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2542 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2543 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2544 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2546 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2547 n_att_selected = g_list_length (selected_attachments);
2548 g_list_free (selected_attachments);
2550 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2551 gtk_action_set_sensitive (action, n_att_selected == 1);
2554 update_paste_dimming (window);
2558 update_window_title (ModestMsgEditWindow *window)
2560 ModestMsgEditWindowPrivate *priv = NULL;
2561 const gchar *subject;
2563 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2564 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2565 if (subject == NULL || subject[0] == '\0')
2566 subject = _("mail_va_new_email");
2568 gtk_window_set_title (GTK_WINDOW (window), subject);
2573 subject_field_changed (GtkEditable *editable,
2574 ModestMsgEditWindow *window)
2576 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2577 update_window_title (window);
2578 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2582 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2585 ModestMsgEditWindowPrivate *priv = NULL;
2587 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2588 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2590 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2592 gtk_widget_show_all (priv->find_toolbar);
2593 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2595 gtk_widget_hide_all (priv->find_toolbar);
2596 gtk_widget_grab_focus (priv->msg_body);
2602 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2603 ModestMsgEditWindow *window)
2605 gchar *current_search = NULL;
2606 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2608 GtkTextIter selection_start, selection_end;
2609 GtkTextIter match_start, match_end;
2611 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2612 if ((current_search == NULL) && (strcmp (current_search, "") == 0)) {
2613 g_free (current_search);
2617 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2618 result = gtk_text_iter_forward_search (&selection_end, current_search, GTK_TEXT_SEARCH_VISIBLE_ONLY, &match_start, &match_end, NULL);
2620 GtkTextIter buffer_start;
2621 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2622 result = gtk_text_iter_forward_search (&buffer_start, current_search, GTK_TEXT_SEARCH_VISIBLE_ONLY, &match_start, &match_end, &selection_start);
2625 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2626 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2628 /* TODO: warning about non succesful search */
2630 g_free (current_search);
2634 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2635 ModestMsgEditWindow *window)
2637 GtkToggleAction *toggle;
2638 ModestWindowPrivate *parent_priv;
2639 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2641 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2642 gtk_toggle_action_set_active (toggle, FALSE);
2647 update_paste_dimming (ModestMsgEditWindow *window)
2649 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2650 GtkAction *action = NULL;
2651 GtkClipboard *clipboard = NULL;
2653 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2655 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2656 gtk_action_set_sensitive (action, gtk_clipboard_wait_is_text_available (clipboard));
2661 modest_msg_edit_window_system_clipboard_owner_change (GtkClipboard *clipboard,
2663 ModestMsgEditWindow *window)
2665 update_paste_dimming (window);