1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
41 #include <modest-account-mgr.h>
42 #include <modest-account-mgr-helpers.h>
44 #include <widgets/modest-msg-edit-window.h>
45 #include <widgets/modest-combo-box.h>
46 #include <widgets/modest-recpt-editor.h>
47 #include <widgets/modest-attachments-view.h>
49 #include <modest-runtime.h>
51 #include "modest-platform.h"
52 #include "modest-icon-names.h"
53 #include "modest-widget-memory.h"
54 #include "modest-window-priv.h"
55 #include "modest-mail-operation.h"
56 #include "modest-tny-platform-factory.h"
57 #include "modest-tny-msg.h"
58 #include "modest-address-book.h"
59 #include "modest-text-utils.h"
60 #include <tny-simple-list.h>
61 #include <wptextview.h>
62 #include <wptextbuffer.h>
63 #include "modest-scroll-area.h"
65 #include "modest-hildon-includes.h"
66 #include "widgets/modest-msg-edit-window-ui.h"
67 #include <libgnomevfs/gnome-vfs-mime.h>
70 #define DEFAULT_FONT_SIZE 3
71 #define DEFAULT_FONT 2
72 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
73 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
74 #define DEFAULT_MAIN_VBOX_SPACING 6
75 #define SUBJECT_MAX_LENGTH 1000
77 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
78 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
79 static void modest_msg_edit_window_finalize (GObject *obj);
81 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
82 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
83 static void send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
84 static void style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
85 static void setup_insensitive_handlers (ModestMsgEditWindow *editor);
86 static void reset_modified (ModestMsgEditWindow *editor);
87 static gboolean is_modified (ModestMsgEditWindow *editor);
89 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
90 static void text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata);
91 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
92 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
93 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
94 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
96 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
98 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
100 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
101 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
102 GdkEventWindowState *event,
104 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
105 ModestRecptEditor *editor);
106 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
107 ModestMsgEditWindow *window);
109 /* ModestWindow methods implementation */
110 static void modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom);
111 static gdouble modest_msg_edit_window_get_zoom (ModestWindow *window);
112 static gboolean modest_msg_edit_window_zoom_minus (ModestWindow *window);
113 static gboolean modest_msg_edit_window_zoom_plus (ModestWindow *window);
114 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
115 gboolean show_toolbar);
116 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
118 ModestMsgEditWindow *window);
119 static void update_window_title (ModestMsgEditWindow *window);
120 static void update_dimmed (ModestMsgEditWindow *window);
123 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
124 ModestMsgEditWindow *window);
125 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
126 ModestMsgEditWindow *window);
128 /* list my signals */
135 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
136 struct _ModestMsgEditWindowPrivate {
138 GtkWidget *header_box;
140 ModestPairList *from_field_protos;
141 GtkWidget *from_field;
145 GtkWidget *bcc_field;
146 GtkWidget *subject_field;
147 GtkWidget *attachments_view;
148 GtkWidget *priority_icon;
149 GtkWidget *add_attachment_button;
151 GtkWidget *cc_caption;
152 GtkWidget *bcc_caption;
153 GtkWidget *attachments_caption;
155 GtkTextBuffer *text_buffer;
157 GtkWidget *font_size_toolitem;
158 GtkWidget *font_face_toolitem;
159 GtkWidget *font_color_button;
160 GSList *font_items_group;
161 GtkWidget *font_tool_button_label;
162 GSList *size_items_group;
163 GtkWidget *size_tool_button_label;
165 GtkWidget *find_toolbar;
172 TnyHeaderFlags priority_flags;
176 gulong clipboard_change_handler_id;
181 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
182 MODEST_TYPE_MSG_EDIT_WINDOW, \
183 ModestMsgEditWindowPrivate))
185 static GtkWindowClass *parent_class = NULL;
187 /* uncomment the following if you have defined any signals */
188 /* static guint signals[LAST_SIGNAL] = {0}; */
191 modest_msg_edit_window_get_type (void)
193 static GType my_type = 0;
195 static const GTypeInfo my_info = {
196 sizeof(ModestMsgEditWindowClass),
197 NULL, /* base init */
198 NULL, /* base finalize */
199 (GClassInitFunc) modest_msg_edit_window_class_init,
200 NULL, /* class finalize */
201 NULL, /* class data */
202 sizeof(ModestMsgEditWindow),
204 (GInstanceInitFunc) modest_msg_edit_window_init,
207 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
208 "ModestMsgEditWindow",
211 wp_text_buffer_library_init ();
217 save_state (ModestWindow *self)
219 modest_widget_memory_save (modest_runtime_get_conf(),
220 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
225 restore_settings (ModestMsgEditWindow *self)
227 modest_widget_memory_restore (modest_runtime_get_conf(),
228 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
233 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
235 GObjectClass *gobject_class;
236 ModestWindowClass *modest_window_class;
237 gobject_class = (GObjectClass*) klass;
238 modest_window_class = (ModestWindowClass*) klass;
240 parent_class = g_type_class_peek_parent (klass);
241 gobject_class->finalize = modest_msg_edit_window_finalize;
243 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
244 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
245 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
246 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
247 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
249 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
251 modest_window_class->save_state_func = save_state;
255 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
257 ModestMsgEditWindowPrivate *priv;
258 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
260 priv->msg_body = NULL;
261 priv->from_field = NULL;
262 priv->to_field = NULL;
263 priv->cc_field = NULL;
264 priv->bcc_field = NULL;
265 priv->subject_field = NULL;
266 priv->attachments = NULL;
268 priv->zoom_level = 1.0;
270 priv->cc_caption = NULL;
271 priv->bcc_caption = NULL;
273 priv->priority_flags = 0;
275 priv->find_toolbar = NULL;
277 priv->draft_msg = NULL;
278 priv->clipboard_change_handler_id = 0;
282 /* FIXME: this is a dup from the one in gtk/ */
285 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
287 static ModestPairList*
288 get_transports (void)
290 GSList *transports = NULL;
292 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
293 GSList *accounts = modest_account_mgr_account_names (account_mgr,
294 TRUE /* only enabled accounts. */);
296 GSList *cursor = accounts;
298 gchar *account_name = cursor->data;
299 gchar *from_string = NULL;
301 from_string = modest_account_mgr_get_from_string (account_mgr,
305 if (from_string && account_name) {
306 gchar *name = account_name;
307 ModestPair *pair = modest_pair_new ((gpointer) name,
308 (gpointer) from_string , TRUE);
309 transports = g_slist_prepend (transports, pair);
312 cursor = cursor->next;
314 g_slist_free (accounts); /* only free the accounts, not the elements,
315 * because they are used in the pairlist */
321 init_window (ModestMsgEditWindow *obj)
323 GtkWidget *from_caption, *to_caption, *subject_caption;
324 GtkWidget *main_vbox;
325 ModestMsgEditWindowPrivate *priv;
327 GtkSizeGroup *size_group;
329 GtkWidget *scroll_area;
330 GtkWidget *subject_box;
331 GtkWidget *attachment_icon;
332 GtkWidget *window_box;
334 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
336 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
338 /* Note: This ModestPairList* must exist for as long as the combo
339 * that uses it, because the ModestComboBox uses the ID opaquely,
340 * so it can't know how to manage its memory. */
341 priv->from_field_protos = get_transports ();
343 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
345 priv->to_field = modest_recpt_editor_new ();
346 priv->cc_field = modest_recpt_editor_new ();
347 priv->bcc_field = modest_recpt_editor_new ();
348 subject_box = gtk_hbox_new (FALSE, 0);
349 priv->priority_icon = gtk_image_new ();
350 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
351 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
352 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
353 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
354 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
355 priv->add_attachment_button = gtk_button_new ();
356 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
357 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
358 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
359 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
360 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
361 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
362 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
363 priv->attachments_view = modest_attachments_view_new (NULL);
365 priv->header_box = gtk_vbox_new (FALSE, 0);
367 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
368 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
369 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
370 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
371 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
372 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
373 g_object_unref (size_group);
375 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
376 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
377 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
378 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
379 gtk_size_group_add_widget (size_group, priv->subject_field);
380 gtk_size_group_add_widget (size_group, priv->attachments_view);
381 g_object_unref (size_group);
383 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
384 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
385 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
386 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
387 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
388 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
389 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
392 priv->msg_body = wp_text_view_new ();
393 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
394 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
395 g_object_set (priv->text_buffer, "font_scale", 1.0, NULL);
396 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
397 /* gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
398 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
400 priv->find_toolbar = hildon_find_toolbar_new (NULL);
401 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
403 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
404 G_CALLBACK (text_buffer_refresh_attributes), obj);
405 g_signal_connect (G_OBJECT (priv->text_buffer), "delete-range",
406 G_CALLBACK (text_buffer_delete_range), obj);
407 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
408 G_CALLBACK (text_buffer_can_undo), obj);
409 g_signal_connect (G_OBJECT (obj), "window-state-event",
410 G_CALLBACK (modest_msg_edit_window_window_state_event),
412 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
413 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
414 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
415 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
416 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
417 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
419 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
420 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
422 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
423 G_CALLBACK (msg_body_focus), obj);
424 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
425 G_CALLBACK (msg_body_focus), obj);
426 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
427 "changed", G_CALLBACK (recpt_field_changed), obj);
428 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
429 "changed", G_CALLBACK (recpt_field_changed), obj);
430 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
431 "changed", G_CALLBACK (recpt_field_changed), obj);
432 recpt_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
433 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
435 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
436 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
438 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
439 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
440 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
442 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
444 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
445 frame = gtk_frame_new (NULL);
446 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
448 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
449 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
450 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
452 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL)) {
453 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
454 gtk_widget_hide (priv->cc_caption);
456 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL)) {
457 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
458 gtk_widget_hide (priv->bcc_caption);
461 window_box = gtk_vbox_new (FALSE, 0);
462 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
463 gtk_box_pack_end (GTK_BOX (window_box), priv->find_toolbar, FALSE, FALSE, 0);
464 gtk_container_add (GTK_CONTAINER(obj), window_box);
465 scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
466 gtk_container_add (GTK_CONTAINER (frame), scroll_area);
467 gtk_container_set_focus_vadjustment (GTK_CONTAINER (scroll_area),
468 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
470 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
471 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
477 modest_msg_edit_window_finalize (GObject *obj)
479 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
481 if (priv->clipboard_change_handler_id > 0) {
482 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), priv->clipboard_change_handler_id);
483 priv->clipboard_change_handler_id = 0;
486 /* This had to stay alive for as long as the combobox that used it: */
487 modest_pair_list_free (priv->from_field_protos);
489 G_OBJECT_CLASS(parent_class)->finalize (obj);
493 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMsgEditWindow *self)
495 GtkWidget *close_dialog;
496 ModestMsgEditWindowPrivate *priv;
499 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
500 modest_window_save_state (MODEST_WINDOW (self));
501 if (is_modified (self)) {
502 close_dialog = hildon_note_new_confirmation (GTK_WINDOW (self), _("mcen_nc_no_email_message_modified_save_changes"));
503 response = gtk_dialog_run (GTK_DIALOG (close_dialog));
504 gtk_widget_destroy (close_dialog);
506 if (response != GTK_RESPONSE_CANCEL) {
507 modest_ui_actions_on_save_to_drafts (NULL, self);
510 /* /\* remove old message from drafts *\/ */
511 /* if (priv->draft_msg) { */
512 /* TnyHeader *header = tny_msg_get_header (priv->draft_msg); */
513 /* TnyAccount *account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(), */
515 /* TNY_ACCOUNT_TYPE_STORE); */
516 /* TnyFolder *folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS); */
517 /* g_return_val_if_fail (TNY_IS_HEADER (header), FALSE); */
518 /* g_return_val_if_fail (TNY_IS_FOLDER (folder), FALSE); */
519 /* tny_folder_remove_msg (folder, header, NULL); */
520 /* g_object_unref (folder); */
521 /* g_object_unref (header); */
522 /* g_object_unref (priv->draft_msg); */
523 /* priv->draft_msg = NULL; */
525 gtk_widget_destroy (GTK_WIDGET (self));
531 menubar_to_menu (GtkUIManager *ui_manager)
533 GtkWidget *main_menu;
537 /* Create new main menu */
538 main_menu = gtk_menu_new();
540 /* Get the menubar from the UI manager */
541 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
543 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
547 menu = GTK_WIDGET (iter->data);
548 gtk_widget_reparent(menu, main_menu);
550 iter = g_list_next (iter);
557 set_msg (ModestMsgEditWindow *self, TnyMsg *msg)
560 const gchar *to, *cc, *bcc, *subject;
562 ModestMsgEditWindowPrivate *priv;
564 TnyHeaderFlags priority_flags;
566 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
567 g_return_if_fail (TNY_IS_MSG (msg));
569 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
571 header = tny_msg_get_header (msg);
572 to = tny_header_get_to (header);
573 cc = tny_header_get_cc (header);
574 bcc = tny_header_get_bcc (header);
575 subject = tny_header_get_subject (header);
576 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
579 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
581 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
583 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
585 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
586 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
589 update_window_title (self);
591 /* gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
592 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
593 body = modest_tny_msg_get_body (msg, TRUE);
595 if ((body == NULL)||(body[0] == '\0')) {
597 body = modest_text_utils_convert_to_html ("");
599 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
600 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
603 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
606 /* Get the default format required from configuration */
607 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
608 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
611 /* Set the default focus depending on having already a To: field or not */
612 if ((!to)||(*to == '\0')) {
613 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
615 gtk_widget_grab_focus (priv->msg_body);
618 /* TODO: lower priority, select in the From: combo to the
619 value that comes from msg <- not sure, should it be
622 /* Add attachments to the view */
623 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
624 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
625 if (priv->attachments == NULL) {
626 gtk_widget_hide (priv->attachments_caption);
628 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
629 gtk_widget_show_all (priv->attachments_caption);
632 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
633 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
635 reset_modified (self);
637 update_dimmed (self);
638 text_buffer_can_undo (priv->text_buffer, FALSE, self);
640 priv->draft_msg = msg;
644 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
647 GList *item_children, *node;
648 GtkWidget *bin_child;
650 bin_child = gtk_bin_get_child (GTK_BIN(item));
652 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
654 for (node = item_children; node != NULL; node = g_list_next (node)) {
655 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
656 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
659 g_list_free (item_children);
663 menu_tool_button_dont_expand (GtkMenuToolButton *item)
666 GList *item_children, *node;
668 box = gtk_bin_get_child (GTK_BIN (item));
669 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
670 item_children = gtk_container_get_children (GTK_CONTAINER (box));
672 for (node = item_children; node != NULL; node = g_list_next (node)) {
673 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
674 if (GTK_IS_TOGGLE_BUTTON (node->data))
675 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
676 else if (GTK_IS_BUTTON (node->data))
677 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
679 g_list_free (item_children);
684 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
686 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
687 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
688 GtkWidget *placeholder;
689 GtkWidget *tool_item;
694 GtkWidget *sizes_menu;
695 GtkWidget *fonts_menu;
696 GSList *radio_group = NULL;
701 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
702 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
704 /* should we hide the toolbar? */
705 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
706 gtk_widget_hide (parent_priv->toolbar);
708 /* Font color placeholder */
709 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
710 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
713 tool_item = GTK_WIDGET (gtk_tool_item_new ());
714 priv->font_color_button = hildon_color_button_new ();
715 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
716 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
717 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
718 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
719 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
720 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
721 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
723 /* Font size and face placeholder */
724 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
725 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
727 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
728 priv->size_tool_button_label = gtk_label_new (NULL);
729 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
730 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
731 size_text,"</span>", NULL);
732 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
734 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
735 sizes_menu = gtk_menu_new ();
736 priv->size_items_group = NULL;
738 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
739 GtkWidget *size_menu_item;
741 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
742 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
743 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
744 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
745 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
746 gtk_widget_show (size_menu_item);
748 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
752 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
753 GtkWidget *item = (GtkWidget *) node->data;
754 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
758 priv->size_items_group = g_slist_reverse (priv->size_items_group);
759 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
760 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
761 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
762 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
763 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
764 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
765 priv->font_size_toolitem = tool_item;
768 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
769 priv->font_tool_button_label = gtk_label_new (NULL);
770 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
771 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
773 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
774 fonts_menu = gtk_menu_new ();
775 priv->font_items_group = NULL;
777 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
778 GtkWidget *font_menu_item;
779 GtkWidget *child_label;
781 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
782 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
783 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
784 wp_get_font_name (font_index), "</span>", NULL);
785 gtk_label_set_markup (GTK_LABEL (child_label), markup);
788 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
789 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
790 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
791 gtk_widget_show (font_menu_item);
793 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
796 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
797 GtkWidget *item = (GtkWidget *) node->data;
798 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
801 priv->font_items_group = g_slist_reverse (priv->font_items_group);
802 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
803 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
804 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
805 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
806 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
807 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
808 priv->font_face_toolitem = tool_item;
810 /* Set expand and homogeneous for remaining items */
811 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
812 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
813 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
814 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
815 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
816 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
817 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
818 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
819 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
827 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name)
830 ModestWindowPrivate *parent_priv;
831 ModestMsgEditWindowPrivate *priv;
832 GtkActionGroup *action_group;
833 GError *error = NULL;
834 GdkPixbuf *window_icon = NULL;
837 gboolean prefer_formatted;
839 ModestPair *account_pair = NULL;
841 g_return_val_if_fail (msg, NULL);
842 g_return_val_if_fail (account_name, NULL);
844 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
846 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
847 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
849 parent_priv->ui_manager = gtk_ui_manager_new();
850 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
851 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
853 /* Add common actions */
854 gtk_action_group_add_actions (action_group,
855 modest_msg_edit_action_entries,
856 G_N_ELEMENTS (modest_msg_edit_action_entries),
858 gtk_action_group_add_toggle_actions (action_group,
859 modest_msg_edit_toggle_action_entries,
860 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
862 gtk_action_group_add_radio_actions (action_group,
863 modest_msg_edit_alignment_radio_action_entries,
864 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
866 G_CALLBACK (modest_ui_actions_on_change_justify),
868 gtk_action_group_add_radio_actions (action_group,
869 modest_msg_edit_zoom_action_entries,
870 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
872 G_CALLBACK (modest_ui_actions_on_change_zoom),
874 gtk_action_group_add_radio_actions (action_group,
875 modest_msg_edit_priority_action_entries,
876 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
878 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
880 gtk_action_group_add_radio_actions (action_group,
881 modest_msg_edit_file_format_action_entries,
882 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
883 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
884 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
886 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
887 g_object_unref (action_group);
889 /* Load the UI definition */
890 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
893 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
894 g_clear_error (&error);
897 /* Add accelerators */
898 gtk_window_add_accel_group (GTK_WINDOW (obj),
899 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
902 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
903 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
906 init_window (MODEST_MSG_EDIT_WINDOW(obj));
908 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
910 gtk_window_set_icon_from_file (GTK_WINDOW(obj), MODEST_APP_ICON, NULL);
912 g_signal_connect (G_OBJECT(obj), "delete-event",
913 G_CALLBACK(on_delete_event), obj);
915 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
917 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
919 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
921 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
922 if (account_pair != NULL)
923 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
925 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg);
927 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
929 /* Set window icon */
930 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
931 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
933 /* Dim at start clipboard actions */
934 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
935 gtk_action_set_sensitive (action, FALSE);
936 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
937 gtk_action_set_sensitive (action, FALSE);
939 /* set initial state of cc and bcc */
940 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
941 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
942 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
943 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
944 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
945 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
947 /* Setup the file format */
948 conf = modest_runtime_get_conf ();
949 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
951 g_clear_error (&error);
952 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
954 file_format = (prefer_formatted) ?
955 MODEST_FILE_FORMAT_FORMATTED_TEXT :
956 MODEST_FILE_FORMAT_PLAIN_TEXT;
957 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
959 return (ModestWindow*) obj;
963 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
965 GString **string_buffer = (GString **) user_data;
967 *string_buffer = g_string_append (*string_buffer, buffer);
973 * @result: A new string which should be freed with g_free().
976 get_formatted_data (ModestMsgEditWindow *edit_window)
978 ModestMsgEditWindowPrivate *priv;
979 GString *string_buffer = g_string_new ("");
981 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
983 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
985 return g_string_free (string_buffer, FALSE);
990 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
993 const gchar *account_name;
994 ModestMsgEditWindowPrivate *priv;
996 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
998 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1000 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1001 g_return_val_if_fail (account_name, NULL);
1004 /* don't free these (except from) */
1005 data = g_slice_new0 (MsgData);
1006 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1008 data->account_name = g_strdup (account_name);
1009 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1010 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1011 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1012 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1013 if (priv->draft_msg) {
1014 data->draft_msg = g_object_ref (priv->draft_msg);
1016 data->draft_msg = NULL;
1019 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1021 gtk_text_buffer_get_bounds (buf, &b, &e);
1022 data->plain_body = g_strdup (gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE)); /* returns a copy */
1024 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1025 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1027 data->html_body = NULL;
1029 data->attachments = priv->attachments; /* TODO: copy and free ? */
1030 data->priority_flags = priv->priority_flags;
1035 /* TODO: We must duplicate this implementation for GNOME and Maemo, but that is unwise. */
1037 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1040 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1048 g_free (data->subject);
1049 g_free (data->plain_body);
1050 g_free (data->html_body);
1051 if (data->draft_msg != NULL) {
1052 g_object_unref (data->draft_msg);
1053 data->draft_msg = NULL;
1055 g_free (data->account_name);
1057 /* TODO: Free data->attachments? */
1059 g_slice_free (MsgData, data);
1063 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1066 ModestMsgEditWindowPrivate *priv = NULL;
1067 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1069 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1071 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1073 return MODEST_MSG_EDIT_FORMAT_HTML;
1075 return MODEST_MSG_EDIT_FORMAT_TEXT;
1079 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1080 ModestMsgEditFormat format)
1082 ModestMsgEditWindowPrivate *priv;
1084 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1085 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1088 case MODEST_MSG_EDIT_FORMAT_HTML:
1089 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1091 case MODEST_MSG_EDIT_FORMAT_TEXT:
1092 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1095 g_return_if_reached ();
1099 ModestMsgEditFormatState *
1100 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1102 ModestMsgEditFormatState *format_state = NULL;
1103 ModestMsgEditWindowPrivate *priv;
1104 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1106 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1107 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1109 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1111 format_state = g_new0 (ModestMsgEditFormatState, 1);
1112 format_state->bold = buffer_format->bold&0x1;
1113 format_state->italics = buffer_format->italic&0x1;
1114 format_state->bullet = buffer_format->bullet&0x1;
1115 format_state->color = buffer_format->color;
1116 format_state->font_size = buffer_format->font_size;
1117 format_state->font_family = wp_get_font_name (buffer_format->font);
1118 format_state->justification = buffer_format->justification;
1119 g_free (buffer_format);
1121 return format_state;
1126 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1127 const ModestMsgEditFormatState *format_state)
1129 ModestMsgEditWindowPrivate *priv;
1130 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1131 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1132 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1133 g_return_if_fail (format_state != NULL);
1135 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1136 gtk_widget_grab_focus (priv->msg_body);
1137 buffer_format->bold = (format_state->bold != FALSE);
1138 buffer_format->italic = (format_state->italics != FALSE);
1139 buffer_format->color = format_state->color;
1140 buffer_format->font_size = format_state->font_size;
1141 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1142 buffer_format->justification = format_state->justification;
1143 buffer_format->bullet = format_state->bullet;
1145 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1147 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1148 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1149 buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
1150 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1151 buffer_format->cs.font = (buffer_format->font != current_format->font);
1152 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1153 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1155 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1156 if (buffer_format->cs.bold) {
1157 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1159 if (buffer_format->cs.italic) {
1160 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1162 if (buffer_format->cs.color) {
1163 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1165 if (buffer_format->cs.font_size) {
1166 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->font_size));
1168 if (buffer_format->cs.justification) {
1169 switch (buffer_format->justification) {
1170 case GTK_JUSTIFY_LEFT:
1171 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1173 case GTK_JUSTIFY_CENTER:
1174 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1176 case GTK_JUSTIFY_RIGHT:
1177 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1184 if (buffer_format->cs.font) {
1185 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->font));
1187 if (buffer_format->cs.bullet) {
1188 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((int)buffer_format->bullet));
1190 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1191 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1193 g_free (current_format);
1198 toggle_action_set_active_block_notify (GtkToggleAction *action,
1201 GSList *proxies = NULL;
1203 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1204 proxies != NULL; proxies = g_slist_next (proxies)) {
1205 GtkWidget *widget = (GtkWidget *) proxies->data;
1206 gtk_action_block_activate_from (GTK_ACTION (action), widget);
1209 gtk_toggle_action_set_active (action, value);
1211 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1212 proxies != NULL; proxies = g_slist_next (proxies)) {
1213 GtkWidget *widget = (GtkWidget *) proxies->data;
1214 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
1219 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1221 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1223 ModestWindowPrivate *parent_priv;
1224 ModestMsgEditWindowPrivate *priv;
1225 GtkWidget *new_size_menuitem;
1226 GtkWidget *new_font_menuitem;
1228 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1229 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1231 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1232 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1233 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1234 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1236 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1237 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1238 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1241 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1243 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1244 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1246 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1247 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1249 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1250 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1252 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1253 G_CALLBACK (modest_msg_edit_window_color_button_change),
1255 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1256 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1257 G_CALLBACK (modest_msg_edit_window_color_button_change),
1260 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1261 buffer_format->font_size))->data);
1262 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1266 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1267 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1268 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1270 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1271 G_CALLBACK (modest_msg_edit_window_size_change),
1273 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1274 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1275 G_CALLBACK (modest_msg_edit_window_size_change),
1279 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1280 buffer_format->font))->data);
1281 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1285 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1286 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1287 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1289 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1290 G_CALLBACK (modest_msg_edit_window_font_change),
1292 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1293 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1294 G_CALLBACK (modest_msg_edit_window_font_change),
1298 g_free (buffer_format);
1304 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1307 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1308 ModestMsgEditWindowPrivate *priv;
1309 GtkWidget *dialog = NULL;
1311 const GdkColor *new_color = NULL;
1313 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1314 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1316 #ifdef MODEST_HILDON_VERSION_0
1317 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1318 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1320 dialog = hildon_color_chooser_new ();
1321 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1322 #endif /*MODEST_HILDON_VERSION_0*/
1323 g_free (buffer_format);
1325 response = gtk_dialog_run (GTK_DIALOG (dialog));
1327 case GTK_RESPONSE_OK: {
1328 #ifdef MODEST_HILDON_VERSION_0
1329 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1332 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1334 #endif /*MODEST_HILDON_VERSION_0*/
1341 gtk_widget_destroy (dialog);
1343 if (new_color != NULL)
1344 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1349 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1352 ModestMsgEditWindowPrivate *priv;
1353 GtkWidget *dialog = NULL;
1355 GdkColor *old_color = NULL;
1356 const GdkColor *new_color = NULL;
1358 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1359 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1361 #ifdef MODEST_HILDON_VERSION_0
1362 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1363 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1365 dialog = hildon_color_chooser_new ();
1366 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1367 #endif /*MODEST_HILDON_VERSION_9*/
1369 response = gtk_dialog_run (GTK_DIALOG (dialog));
1371 case GTK_RESPONSE_OK: {
1372 #ifdef MODEST_HILDON_VERSION_0
1373 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1376 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1378 #endif /*MODEST_HILDON_VERSION_0*/
1384 gtk_widget_destroy (dialog);
1386 if (new_color != NULL)
1387 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1392 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1395 ModestMsgEditWindowPrivate *priv;
1396 GtkWidget *dialog = NULL;
1398 gchar *filename = NULL;
1400 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1402 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1404 response = gtk_dialog_run (GTK_DIALOG (dialog));
1406 case GTK_RESPONSE_OK:
1407 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1412 gtk_widget_destroy (dialog);
1415 GdkPixbuf *pixbuf = NULL;
1416 GtkTextIter position;
1417 GtkTextMark *insert_mark;
1419 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
1422 GdkPixbufFormat *pixbuf_format;
1424 image_file_id = g_open (filename, O_RDONLY, 0);
1425 pixbuf_format = gdk_pixbuf_get_file_info (filename, NULL, NULL);
1426 if ((image_file_id != -1)&&(pixbuf_format != NULL)) {
1427 TnyMimePart *image_part;
1428 TnyStream *image_stream;
1434 mime_types = gdk_pixbuf_format_get_mime_types (pixbuf_format);
1435 if ((mime_types != NULL) && (mime_types[0] != NULL)) {
1436 mime_type = mime_types[0];
1438 mime_type = "image/unknown";
1440 image_part = tny_platform_factory_new_mime_part
1441 (modest_runtime_get_platform_factory ());
1442 image_stream = TNY_STREAM (tny_fs_stream_new (image_file_id));
1444 tny_mime_part_construct_from_stream (image_part, image_stream, mime_type);
1445 g_strfreev (mime_types);
1447 content_id = g_strdup_printf ("%d", priv->last_cid);
1448 tny_mime_part_set_content_id (image_part, content_id);
1449 g_free (content_id);
1452 basename = g_path_get_basename (filename);
1453 tny_mime_part_set_filename (image_part, basename);
1456 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1457 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1458 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (image_part)), pixbuf);
1459 priv->attachments = g_list_prepend (priv->attachments, image_part);
1460 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1462 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1463 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1464 gtk_widget_show_all (priv->attachments_caption);
1465 } else if (image_file_id == -1) {
1466 close (image_file_id);
1475 modest_msg_edit_window_attach_file (ModestMsgEditWindow *window)
1478 ModestMsgEditWindowPrivate *priv;
1479 GtkWidget *dialog = NULL;
1481 GSList *uris = NULL;
1484 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1486 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1487 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1489 response = gtk_dialog_run (GTK_DIALOG (dialog));
1491 case GTK_RESPONSE_OK:
1492 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1497 gtk_widget_destroy (dialog);
1499 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1501 GnomeVFSHandle *handle = NULL;
1502 GnomeVFSResult result;
1504 uri = (const gchar *) uri_node->data;
1505 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1506 if (result == GNOME_VFS_OK) {
1507 TnyMimePart *mime_part;
1509 const gchar *mime_type = NULL;
1513 GnomeVFSFileInfo info;
1515 filename = g_filename_from_uri (uri, NULL, NULL);
1517 if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE) == GNOME_VFS_OK)
1518 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1519 mime_part = tny_platform_factory_new_mime_part
1520 (modest_runtime_get_platform_factory ());
1521 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1523 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1525 content_id = g_strdup_printf ("%d", priv->last_cid);
1526 tny_mime_part_set_content_id (mime_part, content_id);
1527 g_free (content_id);
1530 basename = g_path_get_basename (filename);
1531 tny_mime_part_set_filename (mime_part, basename);
1534 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1535 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1537 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1538 gtk_widget_show_all (priv->attachments_caption);
1539 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1544 g_slist_foreach (uris, (GFunc) g_free, NULL);
1545 g_slist_free (uris);
1549 modest_msg_edit_window_attach_file_noninteractive (
1550 ModestMsgEditWindow *window,
1551 const gchar *file_uri)
1554 ModestMsgEditWindowPrivate *priv;
1556 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1561 /* TODO: We should probably try to use only the URI,
1562 * instead of using a filename.
1564 gchar* filename = g_filename_from_uri (file_uri, NULL, NULL);
1566 g_warning("%s: g_filename_from_uri(%s) failed.\n", __FUNCTION__, file_uri);
1569 file_id = g_open (filename, O_RDONLY, 0);
1570 if (file_id != -1) {
1571 TnyMimePart *mime_part;
1573 const gchar *mime_type;
1577 mime_type = gnome_vfs_get_file_mime_type_fast (filename, NULL);
1578 mime_part = tny_platform_factory_new_mime_part
1579 (modest_runtime_get_platform_factory ());
1580 stream = TNY_STREAM (tny_fs_stream_new (file_id));
1582 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1584 content_id = g_strdup_printf ("%d", priv->last_cid);
1585 tny_mime_part_set_content_id (mime_part, content_id);
1586 g_free (content_id);
1589 basename = g_path_get_basename (filename);
1590 tny_mime_part_set_filename (mime_part, basename);
1593 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1594 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1596 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1597 gtk_widget_show_all (priv->attachments_caption);
1598 } else if (file_id == -1) {
1600 g_warning("file to be attached does not exist: %s", filename);
1608 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1611 ModestMsgEditWindowPrivate *priv;
1612 gboolean clean_list = FALSE;
1614 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1615 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1617 if (att_list == NULL) {
1618 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1622 if (att_list == NULL) {
1623 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1625 GtkWidget *confirmation_dialog = NULL;
1626 gboolean dialog_response;
1628 gchar *message = NULL;
1629 const gchar *filename = NULL;
1631 if (att_list->next == NULL) {
1632 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1636 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1637 att_list->next == NULL), filename);
1638 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1640 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1641 gtk_widget_destroy (confirmation_dialog);
1642 if (!dialog_response) {
1644 g_list_free (att_list);
1647 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1649 for (node = att_list; node != NULL; node = g_list_next (node)) {
1650 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1651 const gchar *att_id;
1652 priv->attachments = g_list_remove (priv->attachments, mime_part);
1654 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1656 if (priv->attachments == NULL)
1657 gtk_widget_hide (priv->attachments_caption);
1658 att_id = tny_mime_part_get_content_id (mime_part);
1660 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1662 g_object_unref (mime_part);
1663 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1668 g_list_free (att_list);
1672 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1675 ModestMsgEditWindowPrivate *priv;
1676 GdkColor *new_color;
1677 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1679 #ifdef MODEST_HILDON_VERSION_0
1680 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1683 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1685 #endif /*MODEST_HILDON_VERSION_0*/
1687 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1689 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1694 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1697 ModestMsgEditWindowPrivate *priv;
1698 gint new_size_index;
1699 ModestMsgEditWindow *window;
1702 window = MODEST_MSG_EDIT_WINDOW (userdata);
1703 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1704 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1706 if (gtk_check_menu_item_get_active (menu_item)) {
1708 WPTextBufferFormat format;
1710 memset (&format, 0, sizeof (format));
1711 wp_text_buffer_get_current_state (WP_TEXT_BUFFER (priv->text_buffer), &format);
1713 label = gtk_bin_get_child (GTK_BIN (menu_item));
1715 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1716 format.cs.font_size = TRUE;
1717 format.cs.text_position = TRUE;
1718 format.cs.font = TRUE;
1719 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1720 wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format);
1722 /* if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, */
1723 /* (gpointer) wp_get_font_size_index (new_size_index, 12))) */
1724 /* wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body)); */
1726 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1727 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1728 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1734 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1737 ModestMsgEditWindowPrivate *priv;
1738 gint new_font_index;
1739 ModestMsgEditWindow *window;
1742 window = MODEST_MSG_EDIT_WINDOW (userdata);
1743 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1744 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1746 if (gtk_check_menu_item_get_active (menu_item)) {
1749 label = gtk_bin_get_child (GTK_BIN (menu_item));
1751 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1753 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1754 (gpointer) new_font_index))
1755 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1757 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1758 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1759 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1765 modest_msg_edit_window_set_zoom (ModestWindow *window,
1768 ModestMsgEditWindowPrivate *priv;
1770 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1772 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1773 priv->zoom_level = zoom;
1774 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom);
1778 modest_msg_edit_window_get_zoom (ModestWindow *window)
1780 ModestMsgEditWindowPrivate *priv;
1782 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1784 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1785 return priv->zoom_level;
1789 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1791 ModestWindowPrivate *parent_priv;
1792 GtkRadioAction *zoom_radio_action;
1793 GSList *group, *node;
1795 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1796 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1797 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1799 group = gtk_radio_action_get_group (zoom_radio_action);
1801 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1802 hildon_banner_show_information (NULL, NULL, _("ckct_ib_max_zoom_level_reached"));
1806 for (node = group; node != NULL; node = g_slist_next (node)) {
1807 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1808 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1816 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1818 ModestWindowPrivate *parent_priv;
1819 GtkRadioAction *zoom_radio_action;
1820 GSList *group, *node;
1822 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1823 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1824 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1826 group = gtk_radio_action_get_group (zoom_radio_action);
1828 for (node = group; node != NULL; node = g_slist_next (node)) {
1829 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1830 if (node->next != NULL) {
1831 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1834 hildon_banner_show_information (NULL, NULL, _("ckct_ib_min_zoom_level_reached"));
1842 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1844 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1845 ModestWindowPrivate *parent_priv;
1846 ModestWindowMgr *mgr;
1847 gboolean is_fullscreen;
1848 GtkAction *fs_toggle_action;
1851 mgr = modest_runtime_get_window_mgr ();
1852 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1854 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1856 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1857 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1858 if (is_fullscreen != active)
1859 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1867 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
1869 ModestWindowPrivate *parent_priv;
1870 GtkAction *fs_toggle_action;
1873 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1875 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1876 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
1877 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
1881 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
1884 ModestMsgEditWindowPrivate *priv = NULL;
1885 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1887 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1888 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1890 gtk_widget_show (priv->cc_caption);
1892 gtk_widget_hide (priv->cc_caption);
1893 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
1897 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
1900 ModestMsgEditWindowPrivate *priv = NULL;
1901 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1903 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1904 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1906 gtk_widget_show (priv->bcc_caption);
1908 gtk_widget_hide (priv->bcc_caption);
1909 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
1913 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
1914 ModestRecptEditor *editor)
1916 ModestMsgEditWindowPrivate *priv;
1918 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1919 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
1920 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1922 if (editor == NULL) {
1923 GtkWidget *view_focus;
1924 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
1926 /* This code should be kept in sync with ModestRecptEditor. The
1927 textview inside the recpt editor is the one that really gets the
1928 focus. As it's inside a scrolled window, and this one inside the
1929 hbox recpt editor inherits from, we'll need to go up in the
1930 hierarchy to know if the text view is part of the recpt editor
1931 or if it's a different text entry */
1933 if (gtk_widget_get_parent (view_focus)) {
1934 GtkWidget *first_parent;
1936 first_parent = gtk_widget_get_parent (view_focus);
1937 if (gtk_widget_get_parent (first_parent) &&
1938 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
1939 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
1944 editor = MODEST_RECPT_EDITOR (priv->to_field);
1948 modest_address_book_select_addresses (editor);
1953 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
1955 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1957 modest_msg_edit_window_open_addressbook (window, NULL);
1961 modest_msg_edit_window_show_toolbar (ModestWindow *self,
1962 gboolean show_toolbar)
1964 ModestWindowPrivate *parent_priv;
1966 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1967 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1969 /* FIXME: we can not just use the code of
1970 modest_msg_edit_window_setup_toolbar because it has a
1971 mixture of both initialization and creation code. */
1974 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1976 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1980 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
1981 TnyHeaderFlags priority_flags)
1983 ModestMsgEditWindowPrivate *priv;
1984 ModestWindowPrivate *parent_priv;
1986 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1988 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1989 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1990 priority_flags = priority_flags & (TNY_HEADER_FLAG_HIGH_PRIORITY);
1992 if (priv->priority_flags != priority_flags) {
1993 GtkAction *priority_action = NULL;
1995 priv->priority_flags = priority_flags;
1997 switch (priority_flags) {
1998 case TNY_HEADER_FLAG_HIGH_PRIORITY:
1999 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2000 gtk_widget_show (priv->priority_icon);
2001 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2002 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2004 case TNY_HEADER_FLAG_LOW_PRIORITY:
2005 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2006 gtk_widget_show (priv->priority_icon);
2007 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2008 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2011 gtk_widget_hide (priv->priority_icon);
2012 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2013 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2016 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2017 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2022 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2025 ModestMsgEditWindowPrivate *priv;
2026 gint current_format;
2028 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2030 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2032 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2033 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2035 if (current_format != file_format) {
2036 switch (file_format) {
2037 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2038 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2040 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2044 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2045 response = gtk_dialog_run (GTK_DIALOG (dialog));
2046 gtk_widget_destroy (dialog);
2047 if (response == GTK_RESPONSE_OK)
2048 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2052 update_dimmed (window);
2057 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2060 ModestMsgEditWindowPrivate *priv;
2061 WPTextBufferFormat oldfmt, fmt;
2062 gint old_position = 0;
2066 GdkColor *color = NULL;
2067 gboolean bold, bold_set, italic, italic_set;
2068 gboolean underline, underline_set;
2069 gboolean strikethrough, strikethrough_set;
2070 gboolean position_set;
2071 gboolean font_size_set, font_set, color_set;
2074 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2075 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2077 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2079 /* First we get the currently selected font information */
2080 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2081 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2083 switch (oldfmt.text_position) {
2084 case TEXT_POSITION_NORMAL:
2087 case TEXT_POSITION_SUPERSCRIPT:
2095 g_object_set (G_OBJECT (dialog),
2096 "bold", oldfmt.bold != FALSE,
2097 "bold-set", !oldfmt.cs.bold,
2098 "underline", oldfmt.underline != FALSE,
2099 "underline-set", !oldfmt.cs.underline,
2100 "italic", oldfmt.italic != FALSE,
2101 "italic-set", !oldfmt.cs.italic,
2102 "strikethrough", oldfmt.strikethrough != FALSE,
2103 "strikethrough-set", !oldfmt.cs.strikethrough,
2104 "color", &oldfmt.color,
2105 "color-set", !oldfmt.cs.color,
2106 "size", wp_font_size[oldfmt.font_size],
2107 "size-set", !oldfmt.cs.font_size,
2108 "position", old_position,
2109 "position-set", !oldfmt.cs.text_position,
2110 "family", wp_get_font_name (oldfmt.font),
2111 "family-set", !oldfmt.cs.font,
2114 gtk_widget_show_all (dialog);
2115 response = gtk_dialog_run (GTK_DIALOG (dialog));
2116 if (response == GTK_RESPONSE_OK) {
2118 g_object_get( dialog,
2120 "bold-set", &bold_set,
2121 "underline", &underline,
2122 "underline-set", &underline_set,
2124 "italic-set", &italic_set,
2125 "strikethrough", &strikethrough,
2126 "strikethrough-set", &strikethrough_set,
2128 "color-set", &color_set,
2130 "size-set", &font_size_set,
2131 "family", &font_name,
2132 "family-set", &font_set,
2133 "position", &position,
2134 "position-set", &position_set,
2139 if (response == GTK_RESPONSE_OK) {
2140 memset(&fmt, 0, sizeof(fmt));
2146 fmt.italic = italic;
2147 fmt.cs.italic = TRUE;
2149 if (underline_set) {
2150 fmt.underline = underline;
2151 fmt.cs.underline = TRUE;
2153 if (strikethrough_set) {
2154 fmt.strikethrough = strikethrough;
2155 fmt.cs.strikethrough = TRUE;
2160 ? TEXT_POSITION_NORMAL
2161 : ( ( position == 1 )
2162 ? TEXT_POSITION_SUPERSCRIPT
2163 : TEXT_POSITION_SUBSCRIPT );
2164 fmt.cs.text_position = TRUE;
2168 fmt.cs.color = TRUE;
2171 fmt.font = wp_get_font_index(font_name,
2176 if (font_size_set) {
2177 fmt.font_size = wp_get_font_size_index(
2178 font_size, DEFAULT_FONT_SIZE);
2179 fmt.cs.font_size = TRUE;
2181 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2183 gtk_widget_destroy (dialog);
2185 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2189 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2191 ModestMsgEditWindowPrivate *priv;
2193 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2194 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2196 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2198 update_dimmed (window);
2203 update_dimmed (ModestMsgEditWindow *window)
2205 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2206 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2210 gboolean editor_focused;
2212 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2213 editor_focused = gtk_widget_is_focus (priv->msg_body);
2215 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2216 gtk_action_set_sensitive (action, rich_text && editor_focused);
2217 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2218 gtk_action_set_sensitive (action, rich_text && editor_focused);
2219 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2220 gtk_action_set_sensitive (action, rich_text && editor_focused);
2221 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2222 gtk_action_set_sensitive (action, rich_text && editor_focused);
2223 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2224 gtk_action_set_sensitive (action, rich_text && editor_focused);
2225 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2226 gtk_action_set_sensitive (action, rich_text && editor_focused);
2227 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2228 gtk_action_set_sensitive (action, rich_text && editor_focused);
2229 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2230 gtk_action_set_sensitive (action, rich_text && editor_focused);
2231 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2232 gtk_action_set_sensitive (action, rich_text && editor_focused);
2233 widget = priv->font_color_button;
2234 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2235 widget = priv->font_size_toolitem;
2236 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2237 widget = priv->font_face_toolitem;
2238 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2242 setup_insensitive_handlers (ModestMsgEditWindow *window)
2244 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2245 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2248 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2249 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2250 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2251 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2253 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2254 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2255 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2256 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2257 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2258 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2259 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2260 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2261 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2262 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2263 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2264 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2265 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2266 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2267 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2268 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2269 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2270 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2271 widget = priv->font_color_button;
2272 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2273 widget = priv->font_size_toolitem;
2274 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2275 widget = priv->font_face_toolitem;
2276 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2281 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2283 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2286 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2287 gtk_action_set_sensitive (action, can_undo);
2291 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2294 GtkTextIter match_start, match_end;
2296 if (image_id == NULL)
2299 gtk_text_buffer_get_start_iter (buffer, &iter);
2301 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2302 GSList *tags = gtk_text_iter_get_tags (&match_start);
2304 for (node = tags; node != NULL; node = g_slist_next (node)) {
2305 GtkTextTag *tag = (GtkTextTag *) node->data;
2306 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2307 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2308 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2310 offset = gtk_text_iter_get_offset (&match_start);
2311 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2312 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2316 gtk_text_iter_forward_char (&iter);
2321 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2323 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2324 GtkTextIter real_start, real_end;
2325 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2327 if (gtk_text_iter_compare (start, end) > 0) {
2331 real_start = *start;
2335 GSList *tags = gtk_text_iter_get_tags (&real_start);
2337 for (node = tags; node != NULL; node = g_slist_next (node)) {
2338 GtkTextTag *tag = (GtkTextTag *) node->data;
2339 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2340 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2342 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2344 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2347 } while (gtk_text_iter_forward_char (&real_start)&&
2348 (gtk_text_iter_compare (&real_start, &real_end)<=0));
2352 msg_body_focus (GtkWidget *focus,
2353 GdkEventFocus *event,
2357 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2362 recpt_field_changed (GtkTextBuffer *buffer,
2363 ModestMsgEditWindow *editor)
2365 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2366 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2367 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2368 gboolean dim = FALSE;
2371 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2372 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2373 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2375 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2376 gtk_text_buffer_get_char_count (cc_buffer) +
2377 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2379 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2380 gtk_action_set_sensitive (action, !dim);
2381 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2382 gtk_action_set_sensitive (action, !dim);
2386 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2388 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2392 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2394 gboolean rich_text, editor_focused;
2396 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2397 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2398 editor_focused = gtk_widget_is_focus (priv->msg_body);
2401 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2402 else if (!editor_focused)
2403 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2407 reset_modified (ModestMsgEditWindow *editor)
2409 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2410 GtkTextBuffer *buffer;
2412 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2413 gtk_text_buffer_set_modified (buffer, FALSE);
2414 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2415 gtk_text_buffer_set_modified (buffer, FALSE);
2416 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2417 gtk_text_buffer_set_modified (buffer, FALSE);
2418 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2422 is_modified (ModestMsgEditWindow *editor)
2424 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2425 GtkTextBuffer *buffer;
2427 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2428 if (gtk_text_buffer_get_modified (buffer))
2430 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2431 if (gtk_text_buffer_get_modified (buffer))
2433 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2434 if (gtk_text_buffer_get_modified (buffer))
2436 if (gtk_text_buffer_get_modified (priv->text_buffer))
2443 modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
2445 ModestMsgEditWindowPrivate *priv = NULL;
2447 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2448 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2450 /* check if there's no recipient added */
2451 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2452 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2453 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2454 /* no recipient contents, then select contacts */
2455 modest_msg_edit_window_open_addressbook (window, NULL);
2459 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
2461 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
2463 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
2466 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2473 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2474 ModestMsgEditWindow *window)
2476 modest_msg_edit_window_attach_file (window);
2480 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2482 ModestMsgEditWindow *window)
2484 ModestWindowPrivate *parent_priv;
2489 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2490 selection = gtk_clipboard_wait_for_text (clipboard);
2491 focused = gtk_window_get_focus (GTK_WINDOW (window));
2493 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2494 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2495 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2496 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2500 update_window_title (ModestMsgEditWindow *window)
2502 ModestMsgEditWindowPrivate *priv = NULL;
2503 const gchar *subject;
2505 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2506 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2507 if (subject == NULL || subject[0] == '\0')
2508 subject = _("mail_va_new_email");
2510 gtk_window_set_title (GTK_WINDOW (window), subject);
2515 subject_field_changed (GtkEditable *editable,
2516 ModestMsgEditWindow *window)
2518 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2519 update_window_title (window);
2520 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2524 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2527 ModestMsgEditWindowPrivate *priv = NULL;
2529 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2530 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2532 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2534 gtk_widget_show_all (priv->find_toolbar);
2535 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2537 gtk_widget_hide_all (priv->find_toolbar);
2538 gtk_widget_grab_focus (priv->msg_body);
2544 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2545 ModestMsgEditWindow *window)
2547 gchar *current_search = NULL;
2548 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2550 GtkTextIter selection_start, selection_end;
2551 GtkTextIter match_start, match_end;
2553 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2554 if ((current_search == NULL) && (strcmp (current_search, "") == 0)) {
2555 g_free (current_search);
2559 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2560 result = gtk_text_iter_forward_search (&selection_end, current_search, GTK_TEXT_SEARCH_VISIBLE_ONLY, &match_start, &match_end, NULL);
2562 GtkTextIter buffer_start;
2563 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2564 result = gtk_text_iter_forward_search (&buffer_start, current_search, GTK_TEXT_SEARCH_VISIBLE_ONLY, &match_start, &match_end, &selection_start);
2567 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2568 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2570 /* TODO: warning about non succesful search */
2572 g_free (current_search);
2576 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2577 ModestMsgEditWindow *window)
2579 GtkToggleAction *toggle;
2580 ModestWindowPrivate *parent_priv;
2581 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2583 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2584 gtk_toggle_action_set_active (toggle, FALSE);