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-tny-folder.h"
59 #include "modest-address-book.h"
60 #include "modest-text-utils.h"
61 #include <tny-simple-list.h>
62 #include <wptextview.h>
63 #include <wptextbuffer.h>
64 #include "modest-scroll-area.h"
66 #include "modest-hildon-includes.h"
67 #ifdef MODEST_HAVE_HILDON0_WIDGETS
68 #include <hildon-widgets/hildon-color-chooser.h>
70 #include "widgets/modest-msg-edit-window-ui.h"
71 #ifdef MODEST_HAVE_HILDON0_WIDGETS
72 #include <libgnomevfs/gnome-vfs-mime-utils.h>
74 #include <libgnomevfs/gnome-vfs-mime.h>
76 #include "modest-maemo-utils.h"
79 #define DEFAULT_FONT_SIZE 3
80 #define DEFAULT_FONT 2
81 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
82 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
83 #define DEFAULT_MAIN_VBOX_SPACING 6
84 #define SUBJECT_MAX_LENGTH 1000
85 #define IMAGE_MAX_WIDTH 640
86 #define DEFAULT_FONT_SCALE 1.5
88 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
89 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
90 static void modest_msg_edit_window_finalize (GObject *obj);
92 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
93 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
94 static void send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
95 static void style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
96 static void remove_attachment_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
97 static void zoom_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
98 static void paste_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
99 static void copy_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
100 static void setup_insensitive_handlers (ModestMsgEditWindow *editor);
101 static void reset_modified (ModestMsgEditWindow *editor);
103 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
104 static void text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata);
105 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
106 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
107 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
108 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
109 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
111 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
113 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
115 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
116 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
117 GdkEventWindowState *event,
119 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
120 ModestRecptEditor *editor);
121 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
122 ModestMsgEditWindow *window);
124 /* ModestWindow methods implementation */
125 static void modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom);
126 static gdouble modest_msg_edit_window_get_zoom (ModestWindow *window);
127 static gboolean modest_msg_edit_window_zoom_minus (ModestWindow *window);
128 static gboolean modest_msg_edit_window_zoom_plus (ModestWindow *window);
129 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
130 gboolean show_toolbar);
131 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
133 ModestMsgEditWindow *window);
134 static void modest_msg_edit_window_system_clipboard_owner_change (GtkClipboard *clipboard,
136 ModestMsgEditWindow *window);
137 static void update_window_title (ModestMsgEditWindow *window);
138 static void update_dimmed (ModestMsgEditWindow *window);
139 static void update_paste_dimming (ModestMsgEditWindow *window);
140 static void update_select_all_dimming (ModestMsgEditWindow *window);
141 static void update_zoom_dimming (ModestMsgEditWindow *window);
144 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
145 ModestMsgEditWindow *window);
146 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
147 ModestMsgEditWindow *window);
148 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
150 GtkTextIter *match_start,
151 GtkTextIter *match_end);
155 /* static gboolean */
156 /* on_key_pressed (GtkWidget *self, */
157 /* GdkEventKey *event, */
158 /* gpointer user_data); */
160 static void edit_menu_activated (GtkAction *action,
162 static void view_menu_activated (GtkAction *action,
165 /* list my signals */
172 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
173 struct _ModestMsgEditWindowPrivate {
175 GtkWidget *header_box;
177 ModestPairList *from_field_protos;
178 GtkWidget *from_field;
182 GtkWidget *bcc_field;
183 GtkWidget *subject_field;
184 GtkWidget *attachments_view;
185 GtkWidget *priority_icon;
186 GtkWidget *add_attachment_button;
188 GtkWidget *cc_caption;
189 GtkWidget *bcc_caption;
190 GtkWidget *attachments_caption;
192 GtkTextBuffer *text_buffer;
194 GtkWidget *font_size_toolitem;
195 GtkWidget *font_face_toolitem;
196 GtkWidget *font_color_button;
197 GSList *font_items_group;
198 GtkWidget *font_tool_button_label;
199 GSList *size_items_group;
200 GtkWidget *size_tool_button_label;
202 GtkWidget *find_toolbar;
206 GtkWidget *scroll_area;
211 TnyHeaderFlags priority_flags;
215 gulong clipboard_change_handler_id;
216 gulong system_clipboard_change_handler_id;
222 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
223 MODEST_TYPE_MSG_EDIT_WINDOW, \
224 ModestMsgEditWindowPrivate))
226 static GtkWindowClass *parent_class = NULL;
228 /* uncomment the following if you have defined any signals */
229 /* static guint signals[LAST_SIGNAL] = {0}; */
232 modest_msg_edit_window_get_type (void)
234 static GType my_type = 0;
236 static const GTypeInfo my_info = {
237 sizeof(ModestMsgEditWindowClass),
238 NULL, /* base init */
239 NULL, /* base finalize */
240 (GClassInitFunc) modest_msg_edit_window_class_init,
241 NULL, /* class finalize */
242 NULL, /* class data */
243 sizeof(ModestMsgEditWindow),
245 (GInstanceInitFunc) modest_msg_edit_window_init,
248 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
249 "ModestMsgEditWindow",
252 wp_text_buffer_library_init ();
258 save_state (ModestWindow *self)
260 modest_widget_memory_save (modest_runtime_get_conf(),
261 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
266 restore_settings (ModestMsgEditWindow *self)
268 modest_widget_memory_restore (modest_runtime_get_conf(),
269 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
274 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
276 GObjectClass *gobject_class;
277 ModestWindowClass *modest_window_class;
278 gobject_class = (GObjectClass*) klass;
279 modest_window_class = (ModestWindowClass*) klass;
281 parent_class = g_type_class_peek_parent (klass);
282 gobject_class->finalize = modest_msg_edit_window_finalize;
284 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
285 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
286 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
287 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
288 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
289 modest_window_class->save_state_func = save_state;
291 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
297 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
299 ModestMsgEditWindowPrivate *priv;
300 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
302 priv->msg_body = NULL;
303 priv->from_field = NULL;
304 priv->to_field = NULL;
305 priv->cc_field = NULL;
306 priv->bcc_field = NULL;
307 priv->subject_field = NULL;
308 priv->attachments = NULL;
310 priv->zoom_level = 1.0;
312 priv->cc_caption = NULL;
313 priv->bcc_caption = NULL;
315 priv->priority_flags = 0;
317 priv->find_toolbar = NULL;
318 priv->last_search = NULL;
320 priv->draft_msg = NULL;
321 priv->clipboard_change_handler_id = 0;
322 priv->system_clipboard_change_handler_id = 0;
327 /* FIXME: this is a dup from the one in gtk/ */
330 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
332 static ModestPairList*
333 get_transports (void)
335 GSList *transports = NULL;
337 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
338 GSList *accounts = modest_account_mgr_account_names (account_mgr,
339 TRUE /* only enabled accounts. */);
341 GSList *cursor = accounts;
343 gchar *account_name = cursor->data;
344 gchar *from_string = NULL;
346 from_string = modest_account_mgr_get_from_string (account_mgr,
350 if (from_string && account_name) {
351 gchar *name = account_name;
352 ModestPair *pair = modest_pair_new ((gpointer) name,
353 (gpointer) from_string , TRUE);
354 transports = g_slist_prepend (transports, pair);
357 cursor = cursor->next;
359 g_slist_free (accounts); /* only free the accounts, not the elements,
360 * because they are used in the pairlist */
366 init_window (ModestMsgEditWindow *obj)
368 GtkWidget *from_caption, *to_caption, *subject_caption;
369 GtkWidget *main_vbox;
370 ModestMsgEditWindowPrivate *priv;
372 GtkSizeGroup *size_group;
374 GtkWidget *subject_box;
375 GtkWidget *attachment_icon;
376 GtkWidget *window_box;
378 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
380 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
382 /* Note: This ModestPairList* must exist for as long as the combo
383 * that uses it, because the ModestComboBox uses the ID opaquely,
384 * so it can't know how to manage its memory. */
385 priv->from_field_protos = get_transports ();
387 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
389 priv->to_field = modest_recpt_editor_new ();
390 priv->cc_field = modest_recpt_editor_new ();
391 priv->bcc_field = modest_recpt_editor_new ();
392 subject_box = gtk_hbox_new (FALSE, 0);
393 priv->priority_icon = gtk_image_new ();
394 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
395 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
396 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
397 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
398 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
399 priv->add_attachment_button = gtk_button_new ();
400 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
401 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
402 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
403 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
404 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
405 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
406 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
407 priv->attachments_view = modest_attachments_view_new (NULL);
409 priv->header_box = gtk_vbox_new (FALSE, 0);
411 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
412 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
413 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
414 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
415 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
416 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
417 g_object_unref (size_group);
419 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
420 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
421 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
422 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
423 gtk_size_group_add_widget (size_group, priv->subject_field);
424 gtk_size_group_add_widget (size_group, priv->attachments_view);
425 g_object_unref (size_group);
427 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
428 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
429 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
430 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
431 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
432 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
433 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
436 priv->msg_body = wp_text_view_new ();
437 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
438 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
439 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
440 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
441 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
442 gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
444 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
446 priv->find_toolbar = hildon_find_toolbar_new (NULL);
447 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
449 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
451 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
452 G_CALLBACK (text_buffer_refresh_attributes), obj);
453 g_signal_connect (G_OBJECT (priv->text_buffer), "delete-range",
454 G_CALLBACK (text_buffer_delete_range), obj);
455 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
456 G_CALLBACK (text_buffer_can_undo), obj);
457 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
458 G_CALLBACK (text_buffer_can_redo), obj);
459 g_signal_connect (G_OBJECT (obj), "window-state-event",
460 G_CALLBACK (modest_msg_edit_window_window_state_event),
462 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
463 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
464 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
465 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
466 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
467 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
469 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
470 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
472 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
473 G_CALLBACK (msg_body_focus), obj);
474 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
475 G_CALLBACK (msg_body_focus), obj);
476 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
477 "changed", G_CALLBACK (recpt_field_changed), obj);
478 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
479 "changed", G_CALLBACK (recpt_field_changed), obj);
480 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
481 "changed", G_CALLBACK (recpt_field_changed), obj);
482 recpt_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
483 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
485 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
486 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
488 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
489 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
490 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
492 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
494 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
495 frame = gtk_frame_new (NULL);
496 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
498 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
499 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
500 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
502 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL)) {
503 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
504 gtk_widget_hide (priv->cc_caption);
506 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL)) {
507 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
508 gtk_widget_hide (priv->bcc_caption);
511 window_box = gtk_vbox_new (FALSE, 0);
512 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
513 gtk_box_pack_end (GTK_BOX (window_box), priv->find_toolbar, FALSE, FALSE, 0);
514 gtk_container_add (GTK_CONTAINER(obj), window_box);
515 priv->scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
516 gtk_container_add (GTK_CONTAINER (frame), priv->scroll_area);
519 TODO: scroll_area was never instantiated.
520 Stop building without warnings-as-errors. murrayc.
521 gtk_container_set_focus_vadjustment (GTK_CONTAINER (scroll_area),
522 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
525 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
526 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
527 priv->system_clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
528 G_CALLBACK (modest_msg_edit_window_system_clipboard_owner_change), obj);
534 modest_msg_edit_window_finalize (GObject *obj)
536 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
538 if (priv->clipboard_change_handler_id > 0) {
539 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), priv->clipboard_change_handler_id);
540 priv->clipboard_change_handler_id = 0;
543 if (priv->system_clipboard_change_handler_id > 0) {
544 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
545 priv->system_clipboard_change_handler_id);
546 priv->system_clipboard_change_handler_id = 0;
549 if (priv->draft_msg != NULL) {
550 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
551 if (TNY_IS_HEADER (header)) {
552 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
553 modest_window_mgr_unregister_header (mgr, header);
555 g_object_unref (priv->draft_msg);
556 priv->draft_msg = NULL;
559 /* This had to stay alive for as long as the combobox that used it: */
560 modest_pair_list_free (priv->from_field_protos);
562 G_OBJECT_CLASS(parent_class)->finalize (obj);
566 menubar_to_menu (GtkUIManager *ui_manager)
568 GtkWidget *main_menu;
572 /* Create new main menu */
573 main_menu = gtk_menu_new();
575 /* Get the menubar from the UI manager */
576 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
578 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
582 menu = GTK_WIDGET (iter->data);
583 gtk_widget_reparent(menu, main_menu);
585 iter = g_list_next (iter);
592 set_msg (ModestMsgEditWindow *self, TnyMsg *msg)
595 const gchar *to, *cc, *bcc, *subject;
597 ModestMsgEditWindowPrivate *priv;
599 TnyHeaderFlags priority_flags;
600 TnyFolder *msg_folder;
602 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
603 g_return_if_fail (TNY_IS_MSG (msg));
605 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
607 header = tny_msg_get_header (msg);
608 to = tny_header_get_to (header);
609 cc = tny_header_get_cc (header);
610 bcc = tny_header_get_bcc (header);
611 subject = tny_header_get_subject (header);
612 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
615 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
617 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
618 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
619 gtk_widget_show (priv->cc_caption);
620 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
621 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
622 gtk_widget_hide (priv->cc_caption);
625 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
626 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
627 gtk_widget_show (priv->bcc_caption);
628 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
629 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
630 gtk_widget_hide (priv->bcc_caption);
633 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
634 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
637 update_window_title (self);
639 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
640 body = modest_tny_msg_get_body (msg, TRUE);
642 if ((body == NULL)||(body[0] == '\0')) {
644 body = modest_text_utils_convert_to_html ("");
646 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
647 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
650 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
653 /* Get the default format required from configuration */
654 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
655 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
658 /* Set the default focus depending on having already a To: field or not */
659 if ((!to)||(*to == '\0')) {
660 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
662 gtk_widget_grab_focus (priv->msg_body);
665 /* TODO: lower priority, select in the From: combo to the
666 value that comes from msg <- not sure, should it be
669 /* Add attachments to the view */
670 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
671 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
672 if (priv->attachments == NULL) {
673 gtk_widget_hide (priv->attachments_caption);
675 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
676 gtk_widget_show_all (priv->attachments_caption);
679 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
680 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
682 reset_modified (self);
684 update_dimmed (self);
685 text_buffer_can_undo (priv->text_buffer, FALSE, self);
686 text_buffer_can_redo (priv->text_buffer, FALSE, self);
688 /* we should set a reference to the incoming message if it is a draft */
689 msg_folder = tny_msg_get_folder (msg);
691 if (modest_tny_folder_is_local_folder (msg_folder) &&
692 modest_tny_folder_get_local_folder_type (msg_folder) == TNY_FOLDER_TYPE_DRAFTS)
693 priv->draft_msg = g_object_ref(msg);
694 g_object_unref (msg_folder);
699 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
702 GList *item_children, *node;
703 GtkWidget *bin_child;
705 bin_child = gtk_bin_get_child (GTK_BIN(item));
707 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
709 for (node = item_children; node != NULL; node = g_list_next (node)) {
710 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
711 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
714 g_list_free (item_children);
718 menu_tool_button_dont_expand (GtkMenuToolButton *item)
721 GList *item_children, *node;
723 box = gtk_bin_get_child (GTK_BIN (item));
724 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
725 item_children = gtk_container_get_children (GTK_CONTAINER (box));
727 for (node = item_children; node != NULL; node = g_list_next (node)) {
728 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
729 if (GTK_IS_TOGGLE_BUTTON (node->data))
730 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
731 else if (GTK_IS_BUTTON (node->data))
732 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
734 g_list_free (item_children);
739 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
741 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
742 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
743 GtkWidget *placeholder;
744 GtkWidget *tool_item;
749 GtkWidget *sizes_menu;
750 GtkWidget *fonts_menu;
751 GSList *radio_group = NULL;
756 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
757 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
759 /* should we hide the toolbar? */
760 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
761 gtk_widget_hide (parent_priv->toolbar);
763 /* Font color placeholder */
764 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
765 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
768 tool_item = GTK_WIDGET (gtk_tool_item_new ());
769 priv->font_color_button = hildon_color_button_new ();
770 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
771 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
772 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
773 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
774 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
775 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
776 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
778 /* Font size and face placeholder */
779 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
780 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
782 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
783 priv->size_tool_button_label = gtk_label_new (NULL);
784 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
785 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
786 size_text,"</span>", NULL);
787 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
789 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
790 sizes_menu = gtk_menu_new ();
791 priv->size_items_group = NULL;
793 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
794 GtkWidget *size_menu_item;
796 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
797 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
798 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
799 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
800 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
801 gtk_widget_show (size_menu_item);
803 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
807 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
808 GtkWidget *item = (GtkWidget *) node->data;
809 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
813 priv->size_items_group = g_slist_reverse (priv->size_items_group);
814 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
815 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
816 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
817 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
818 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
819 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
820 priv->font_size_toolitem = tool_item;
823 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
824 priv->font_tool_button_label = gtk_label_new (NULL);
825 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
826 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
828 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
829 fonts_menu = gtk_menu_new ();
830 priv->font_items_group = NULL;
832 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
833 GtkWidget *font_menu_item;
834 GtkWidget *child_label;
836 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
837 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
838 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
839 wp_get_font_name (font_index), "</span>", NULL);
840 gtk_label_set_markup (GTK_LABEL (child_label), markup);
843 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
844 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
845 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
846 gtk_widget_show (font_menu_item);
848 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
851 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
852 GtkWidget *item = (GtkWidget *) node->data;
853 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
856 priv->font_items_group = g_slist_reverse (priv->font_items_group);
857 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
858 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
859 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
860 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
861 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
862 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
863 priv->font_face_toolitem = tool_item;
865 /* Set expand and homogeneous for remaining items */
866 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
867 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
868 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
869 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
870 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
871 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
872 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
873 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
874 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
882 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name)
885 ModestWindowPrivate *parent_priv;
886 ModestMsgEditWindowPrivate *priv;
887 GtkActionGroup *action_group;
888 GError *error = NULL;
889 GdkPixbuf *window_icon = NULL;
892 gboolean prefer_formatted;
894 ModestPair *account_pair = NULL;
896 g_return_val_if_fail (msg, NULL);
897 g_return_val_if_fail (account_name, NULL);
899 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
901 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
902 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
904 parent_priv->ui_manager = gtk_ui_manager_new();
905 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
906 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
908 /* Add common actions */
909 gtk_action_group_add_actions (action_group,
910 modest_msg_edit_action_entries,
911 G_N_ELEMENTS (modest_msg_edit_action_entries),
913 gtk_action_group_add_toggle_actions (action_group,
914 modest_msg_edit_toggle_action_entries,
915 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
917 gtk_action_group_add_radio_actions (action_group,
918 modest_msg_edit_alignment_radio_action_entries,
919 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
921 G_CALLBACK (modest_ui_actions_on_change_justify),
923 gtk_action_group_add_radio_actions (action_group,
924 modest_msg_edit_zoom_action_entries,
925 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
927 G_CALLBACK (modest_ui_actions_on_change_zoom),
929 gtk_action_group_add_radio_actions (action_group,
930 modest_msg_edit_priority_action_entries,
931 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
933 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
935 gtk_action_group_add_radio_actions (action_group,
936 modest_msg_edit_file_format_action_entries,
937 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
938 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
939 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
941 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
942 g_object_unref (action_group);
944 /* Load the UI definition */
945 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
948 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
949 g_clear_error (&error);
952 /* Add accelerators */
953 gtk_window_add_accel_group (GTK_WINDOW (obj),
954 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
957 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
958 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
961 init_window (MODEST_MSG_EDIT_WINDOW(obj));
963 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
965 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
967 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
969 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
971 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
972 if (account_pair != NULL)
973 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
975 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg);
977 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
979 /* Set window icon */
980 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
981 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
983 /* Dim at start clipboard actions */
984 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
985 gtk_action_set_sensitive (action, FALSE);
986 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
987 gtk_action_set_sensitive (action, FALSE);
988 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
989 gtk_action_set_sensitive (action, FALSE);
991 /* Update select all */
992 update_select_all_dimming (MODEST_MSG_EDIT_WINDOW (obj));
993 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu");
994 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (edit_menu_activated), obj);
995 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu");
996 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (view_menu_activated), obj);
998 /* set initial state of cc and bcc */
999 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
1000 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1001 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
1002 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
1003 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1004 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
1006 /* Setup the file format */
1007 conf = modest_runtime_get_conf ();
1008 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
1010 g_clear_error (&error);
1011 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
1013 file_format = (prefer_formatted) ?
1014 MODEST_FILE_FORMAT_FORMATTED_TEXT :
1015 MODEST_FILE_FORMAT_PLAIN_TEXT;
1016 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
1018 update_paste_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1020 return (ModestWindow*) obj;
1024 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1026 GString **string_buffer = (GString **) user_data;
1028 *string_buffer = g_string_append (*string_buffer, buffer);
1034 * @result: A new string which should be freed with g_free().
1037 get_formatted_data (ModestMsgEditWindow *edit_window)
1039 ModestMsgEditWindowPrivate *priv;
1040 GString *string_buffer = g_string_new ("");
1042 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1044 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1046 return g_string_free (string_buffer, FALSE);
1051 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1054 const gchar *account_name;
1055 ModestMsgEditWindowPrivate *priv;
1057 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1059 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1061 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1062 g_return_val_if_fail (account_name, NULL);
1065 /* don't free these (except from) */
1066 data = g_slice_new0 (MsgData);
1067 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1069 data->account_name = g_strdup (account_name);
1070 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1071 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1072 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1073 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1074 if (priv->draft_msg) {
1075 data->draft_msg = g_object_ref (priv->draft_msg);
1077 data->draft_msg = NULL;
1080 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1082 gtk_text_buffer_get_bounds (buf, &b, &e);
1083 data->plain_body = g_strdup (gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE)); /* returns a copy */
1085 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1086 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1088 data->html_body = NULL;
1090 /* deep-copy the data */
1091 GList *cursor = priv->attachments;
1092 data->attachments = NULL;
1094 if (!(TNY_IS_MIME_PART(cursor->data))) {
1095 g_warning ("strange data in attachment list");
1098 data->attachments = g_list_append (data->attachments,
1099 g_object_ref (cursor->data));
1100 cursor = g_list_next (cursor);
1103 data->priority_flags = priv->priority_flags;
1110 unref_gobject (GObject *obj, gpointer data)
1112 if (!G_IS_OBJECT(obj))
1114 g_object_unref (obj);
1118 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1121 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1129 g_free (data->subject);
1130 g_free (data->plain_body);
1131 g_free (data->html_body);
1132 g_free (data->account_name);
1134 if (data->draft_msg != NULL) {
1135 g_object_unref (data->draft_msg);
1136 data->draft_msg = NULL;
1139 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1140 g_list_free (data->attachments);
1142 g_slice_free (MsgData, data);
1146 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1149 ModestMsgEditWindowPrivate *priv = NULL;
1150 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1152 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1154 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1156 return MODEST_MSG_EDIT_FORMAT_HTML;
1158 return MODEST_MSG_EDIT_FORMAT_TEXT;
1162 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1163 ModestMsgEditFormat format)
1165 ModestMsgEditWindowPrivate *priv;
1167 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1168 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1171 case MODEST_MSG_EDIT_FORMAT_HTML:
1172 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1174 case MODEST_MSG_EDIT_FORMAT_TEXT:
1175 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1178 g_return_if_reached ();
1182 ModestMsgEditFormatState *
1183 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1185 ModestMsgEditFormatState *format_state = NULL;
1186 ModestMsgEditWindowPrivate *priv;
1187 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1189 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1190 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1192 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1194 format_state = g_new0 (ModestMsgEditFormatState, 1);
1195 format_state->bold = buffer_format->bold&0x1;
1196 format_state->italics = buffer_format->italic&0x1;
1197 format_state->bullet = buffer_format->bullet&0x1;
1198 format_state->color = buffer_format->color;
1199 format_state->font_size = buffer_format->font_size;
1200 format_state->font_family = wp_get_font_name (buffer_format->font);
1201 format_state->justification = buffer_format->justification;
1202 g_free (buffer_format);
1204 return format_state;
1209 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1210 const ModestMsgEditFormatState *format_state)
1212 ModestMsgEditWindowPrivate *priv;
1213 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1214 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1215 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1216 g_return_if_fail (format_state != NULL);
1218 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1219 gtk_widget_grab_focus (priv->msg_body);
1220 buffer_format->bold = (format_state->bold != FALSE);
1221 buffer_format->italic = (format_state->italics != FALSE);
1222 buffer_format->color = format_state->color;
1223 buffer_format->font_size = format_state->font_size;
1224 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1225 buffer_format->justification = format_state->justification;
1226 buffer_format->bullet = format_state->bullet;
1228 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1230 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1231 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1232 buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
1233 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1234 buffer_format->cs.font = (buffer_format->font != current_format->font);
1235 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1236 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1238 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1239 if (buffer_format->cs.bold) {
1240 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1242 if (buffer_format->cs.italic) {
1243 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1245 if (buffer_format->cs.color) {
1246 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1248 if (buffer_format->cs.font_size) {
1249 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1251 if (buffer_format->cs.justification) {
1252 switch (buffer_format->justification) {
1253 case GTK_JUSTIFY_LEFT:
1254 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1256 case GTK_JUSTIFY_CENTER:
1257 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1259 case GTK_JUSTIFY_RIGHT:
1260 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1267 if (buffer_format->cs.font) {
1268 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1270 if (buffer_format->cs.bullet) {
1271 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((int)buffer_format->bullet));
1273 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1274 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1276 g_free (current_format);
1281 toggle_action_set_active_block_notify (GtkToggleAction *action,
1284 GSList *proxies = NULL;
1286 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1287 proxies != NULL; proxies = g_slist_next (proxies)) {
1288 GtkWidget *widget = (GtkWidget *) proxies->data;
1289 gtk_action_block_activate_from (GTK_ACTION (action), widget);
1292 gtk_toggle_action_set_active (action, value);
1294 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1295 proxies != NULL; proxies = g_slist_next (proxies)) {
1296 GtkWidget *widget = (GtkWidget *) proxies->data;
1297 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
1302 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1304 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1306 ModestWindowPrivate *parent_priv;
1307 ModestMsgEditWindowPrivate *priv;
1308 GtkWidget *new_size_menuitem;
1309 GtkWidget *new_font_menuitem;
1311 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1312 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1314 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1315 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1316 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1317 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1319 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1320 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1321 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1324 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1326 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1327 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1329 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1330 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1332 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1333 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1335 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1336 G_CALLBACK (modest_msg_edit_window_color_button_change),
1338 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1339 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1340 G_CALLBACK (modest_msg_edit_window_color_button_change),
1343 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1344 buffer_format->font_size))->data);
1345 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1349 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1350 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1351 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1353 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1354 G_CALLBACK (modest_msg_edit_window_size_change),
1356 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1357 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1358 G_CALLBACK (modest_msg_edit_window_size_change),
1362 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1363 buffer_format->font))->data);
1364 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1368 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1369 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1370 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1372 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1373 G_CALLBACK (modest_msg_edit_window_font_change),
1375 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1376 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1377 G_CALLBACK (modest_msg_edit_window_font_change),
1381 g_free (buffer_format);
1387 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1390 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1391 ModestMsgEditWindowPrivate *priv;
1392 GtkWidget *dialog = NULL;
1394 const GdkColor *new_color = NULL;
1396 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1397 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1399 #ifdef MODEST_HILDON_VERSION_0
1400 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1401 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1403 dialog = hildon_color_chooser_new ();
1404 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1405 #endif /*MODEST_HILDON_VERSION_0*/
1406 g_free (buffer_format);
1408 response = gtk_dialog_run (GTK_DIALOG (dialog));
1410 case GTK_RESPONSE_OK: {
1411 #ifdef MODEST_HILDON_VERSION_0
1412 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1415 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1417 #endif /*MODEST_HILDON_VERSION_0*/
1424 gtk_widget_destroy (dialog);
1426 if (new_color != NULL)
1427 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1432 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1435 ModestMsgEditWindowPrivate *priv;
1436 GtkWidget *dialog = NULL;
1438 GdkColor *old_color = NULL;
1439 const GdkColor *new_color = NULL;
1441 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1442 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1444 #ifdef MODEST_HILDON_VERSION_0
1445 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1446 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1448 dialog = hildon_color_chooser_new ();
1449 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1450 #endif /*MODEST_HILDON_VERSION_9*/
1452 response = gtk_dialog_run (GTK_DIALOG (dialog));
1454 case GTK_RESPONSE_OK: {
1455 #ifdef MODEST_HILDON_VERSION_0
1456 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1459 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1461 #endif /*MODEST_HILDON_VERSION_0*/
1467 gtk_widget_destroy (dialog);
1469 if (new_color != NULL)
1470 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1476 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1479 ModestMsgEditWindowPrivate *priv;
1480 GtkWidget *dialog = NULL;
1482 GSList *uris = NULL;
1483 GSList *uri_node = NULL;
1485 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1487 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1488 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1489 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1491 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1493 response = gtk_dialog_run (GTK_DIALOG (dialog));
1495 case GTK_RESPONSE_OK:
1496 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1501 gtk_widget_destroy (dialog);
1503 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1505 GnomeVFSHandle *handle = NULL;
1506 GnomeVFSResult result;
1507 GtkTextIter position;
1508 GtkTextMark *insert_mark;
1510 uri = (const gchar *) uri_node->data;
1511 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1512 if (result == GNOME_VFS_OK) {
1513 GdkPixbufLoader *loader;
1515 GnomeVFSFileInfo info;
1516 gchar *filename, *basename;
1517 TnyMimePart *mime_part;
1520 const gchar *mime_type = NULL;
1522 filename = g_filename_from_uri (uri, NULL, NULL);
1523 if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
1525 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1527 mime_part = tny_platform_factory_new_mime_part
1528 (modest_runtime_get_platform_factory ());
1529 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1531 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1533 content_id = g_strdup_printf ("%d", priv->last_cid);
1534 tny_mime_part_set_content_id (mime_part, content_id);
1535 g_free (content_id);
1538 basename = g_path_get_basename (filename);
1539 tny_mime_part_set_filename (mime_part, basename);
1542 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1543 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1545 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1546 gtk_widget_show_all (priv->attachments_caption);
1547 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1550 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1551 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1552 unsigned char read_buffer[128];
1554 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1555 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
1558 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1559 g_object_ref (pixbuf);
1560 gdk_pixbuf_loader_close (loader, NULL);
1561 g_object_unref (loader);
1563 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1564 GdkPixbuf *new_pixbuf;
1566 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1567 gdk_pixbuf_get_width (pixbuf);
1568 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1569 g_object_unref (pixbuf);
1570 pixbuf = new_pixbuf;
1573 if (pixbuf != NULL) {
1574 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1575 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1576 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1585 modest_msg_edit_window_attach_file (ModestMsgEditWindow *window)
1588 ModestMsgEditWindowPrivate *priv;
1589 GtkWidget *dialog = NULL;
1591 GSList *uris = NULL;
1594 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1596 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1597 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1599 response = gtk_dialog_run (GTK_DIALOG (dialog));
1601 case GTK_RESPONSE_OK:
1602 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1607 gtk_widget_destroy (dialog);
1609 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1611 GnomeVFSHandle *handle = NULL;
1612 GnomeVFSResult result;
1614 uri = (const gchar *) uri_node->data;
1615 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1616 if (result == GNOME_VFS_OK) {
1617 TnyMimePart *mime_part;
1619 const gchar *mime_type = NULL;
1623 GnomeVFSFileInfo info;
1625 filename = g_filename_from_uri (uri, NULL, NULL);
1627 if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE) == GNOME_VFS_OK)
1628 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1629 mime_part = tny_platform_factory_new_mime_part
1630 (modest_runtime_get_platform_factory ());
1631 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1633 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1635 content_id = g_strdup_printf ("%d", priv->last_cid);
1636 tny_mime_part_set_content_id (mime_part, content_id);
1637 g_free (content_id);
1640 basename = g_path_get_basename (filename);
1641 tny_mime_part_set_filename (mime_part, basename);
1644 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1645 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1647 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1648 gtk_widget_show_all (priv->attachments_caption);
1649 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1654 g_slist_foreach (uris, (GFunc) g_free, NULL);
1655 g_slist_free (uris);
1659 modest_msg_edit_window_attach_file_noninteractive (
1660 ModestMsgEditWindow *window,
1661 const gchar *file_uri)
1664 ModestMsgEditWindowPrivate *priv;
1666 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1668 if (file_uri && strlen(file_uri)) {
1671 /* TODO: We should probably try to use only the URI,
1672 * instead of using a filename.
1674 gchar* filename = g_filename_from_uri (file_uri, NULL, NULL);
1676 g_warning("%s: g_filename_from_uri('%s') failed.\n", __FUNCTION__, file_uri);
1679 file_id = g_open (filename, O_RDONLY, 0);
1680 if (file_id != -1) {
1681 TnyMimePart *mime_part;
1683 const gchar *mime_type;
1686 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1687 mime_type = gnome_vfs_get_mime_type(filename);
1689 mime_type = gnome_vfs_get_file_mime_type_fast (filename, NULL);
1691 mime_part = tny_platform_factory_new_mime_part
1692 (modest_runtime_get_platform_factory ());
1693 stream = TNY_STREAM (tny_fs_stream_new (file_id));
1695 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1697 content_id = g_strdup_printf ("%d", priv->last_cid);
1698 tny_mime_part_set_content_id (mime_part, content_id);
1699 g_free (content_id);
1702 basename = g_path_get_basename (filename);
1703 tny_mime_part_set_filename (mime_part, basename);
1706 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1707 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1709 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1710 gtk_widget_show_all (priv->attachments_caption);
1711 } else if (file_id == -1) {
1713 g_warning("file to be attached does not exist: %s", filename);
1721 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1724 ModestMsgEditWindowPrivate *priv;
1725 gboolean clean_list = FALSE;
1727 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1728 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1730 if (att_list == NULL) {
1731 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1735 if (att_list == NULL) {
1736 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1738 GtkWidget *confirmation_dialog = NULL;
1739 gboolean dialog_response;
1741 gchar *message = NULL;
1742 const gchar *filename = NULL;
1744 if (att_list->next == NULL) {
1745 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1749 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1750 att_list->next == NULL), filename);
1751 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1753 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1754 gtk_widget_destroy (confirmation_dialog);
1755 if (!dialog_response) {
1757 g_list_free (att_list);
1760 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1762 for (node = att_list; node != NULL; node = g_list_next (node)) {
1763 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1764 const gchar *att_id;
1765 priv->attachments = g_list_remove (priv->attachments, mime_part);
1767 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1769 if (priv->attachments == NULL)
1770 gtk_widget_hide (priv->attachments_caption);
1771 att_id = tny_mime_part_get_content_id (mime_part);
1773 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1775 g_object_unref (mime_part);
1776 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1781 g_list_free (att_list);
1785 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1788 ModestMsgEditWindowPrivate *priv;
1789 GdkColor *new_color;
1790 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1792 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1793 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1796 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1798 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1800 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1802 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1807 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1810 ModestMsgEditWindowPrivate *priv;
1811 gint new_size_index;
1812 ModestMsgEditWindow *window;
1815 window = MODEST_MSG_EDIT_WINDOW (userdata);
1816 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1817 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1819 if (gtk_check_menu_item_get_active (menu_item)) {
1821 WPTextBufferFormat format;
1823 memset (&format, 0, sizeof (format));
1824 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1826 label = gtk_bin_get_child (GTK_BIN (menu_item));
1828 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1829 format.cs.font_size = TRUE;
1830 format.cs.text_position = TRUE;
1831 format.cs.font = TRUE;
1832 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1833 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1835 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1836 (gpointer) wp_get_font_size_index (new_size_index, 12)))
1837 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1839 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1840 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1841 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1847 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1850 ModestMsgEditWindowPrivate *priv;
1851 gint new_font_index;
1852 ModestMsgEditWindow *window;
1855 window = MODEST_MSG_EDIT_WINDOW (userdata);
1856 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1857 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1859 if (gtk_check_menu_item_get_active (menu_item)) {
1862 label = gtk_bin_get_child (GTK_BIN (menu_item));
1864 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1866 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1867 (gpointer) new_font_index))
1868 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1870 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1871 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1872 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1878 modest_msg_edit_window_set_zoom (ModestWindow *window,
1881 ModestMsgEditWindowPrivate *priv;
1882 ModestWindowPrivate *parent_priv;
1883 GtkRadioAction *zoom_radio_action;
1885 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1887 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1888 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1889 priv->zoom_level = zoom;
1890 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom*DEFAULT_FONT_SCALE);
1892 /* Zoom level menu options should be updated with the current zoom level */
1893 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1894 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1895 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1896 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1897 /* FIXME: Not availible before Gtk 2.10 */
1899 gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
1904 modest_msg_edit_window_get_zoom (ModestWindow *window)
1906 ModestMsgEditWindowPrivate *priv;
1908 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1910 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1911 return priv->zoom_level;
1915 zoom_allowed (ModestMsgEditWindow *window)
1919 focus = gtk_window_get_focus (GTK_WINDOW (window));
1920 return (focus != NULL && WP_IS_TEXT_VIEW (focus));
1924 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1926 ModestWindowPrivate *parent_priv;
1927 GtkRadioAction *zoom_radio_action;
1928 GSList *group, *node;
1930 /* First we check if the text view is focused. If not, zooming is not allowed */
1931 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1932 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1936 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1937 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1938 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1940 group = gtk_radio_action_get_group (zoom_radio_action);
1942 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1943 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
1947 for (node = group; node != NULL; node = g_slist_next (node)) {
1948 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1949 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1957 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1959 ModestWindowPrivate *parent_priv;
1960 GtkRadioAction *zoom_radio_action;
1961 GSList *group, *node;
1963 /* First we check if the text view is focused. If not, zooming is not allowed */
1964 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1965 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1969 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1970 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1971 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1973 group = gtk_radio_action_get_group (zoom_radio_action);
1975 for (node = group; node != NULL; node = g_slist_next (node)) {
1976 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1977 if (node->next != NULL) {
1978 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1981 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
1989 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1991 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1992 ModestWindowPrivate *parent_priv;
1993 ModestWindowMgr *mgr;
1994 gboolean is_fullscreen;
1995 GtkAction *fs_toggle_action;
1998 mgr = modest_runtime_get_window_mgr ();
1999 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2001 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2003 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2004 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2005 if (is_fullscreen != active)
2006 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2014 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
2016 ModestWindowPrivate *parent_priv;
2017 GtkAction *fs_toggle_action;
2020 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2022 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2023 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
2024 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
2028 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2031 ModestMsgEditWindowPrivate *priv = NULL;
2032 const gchar *recipients;
2033 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2035 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2036 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2037 recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field));
2038 if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2039 gtk_widget_show (priv->cc_caption);
2041 gtk_widget_hide (priv->cc_caption);
2042 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2046 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2049 ModestMsgEditWindowPrivate *priv = NULL;
2050 const gchar *recipients;
2051 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2053 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2054 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2055 recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field));
2056 if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2057 gtk_widget_show (priv->bcc_caption);
2059 gtk_widget_hide (priv->bcc_caption);
2060 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2064 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2065 ModestRecptEditor *editor)
2067 ModestMsgEditWindowPrivate *priv;
2069 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2070 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2071 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2073 if (editor == NULL) {
2074 GtkWidget *view_focus;
2075 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2077 /* This code should be kept in sync with ModestRecptEditor. The
2078 textview inside the recpt editor is the one that really gets the
2079 focus. As it's inside a scrolled window, and this one inside the
2080 hbox recpt editor inherits from, we'll need to go up in the
2081 hierarchy to know if the text view is part of the recpt editor
2082 or if it's a different text entry */
2084 if (gtk_widget_get_parent (view_focus)) {
2085 GtkWidget *first_parent;
2087 first_parent = gtk_widget_get_parent (view_focus);
2088 if (gtk_widget_get_parent (first_parent) &&
2089 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2090 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2095 editor = MODEST_RECPT_EDITOR (priv->to_field);
2099 modest_address_book_select_addresses (editor);
2104 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2106 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2108 modest_msg_edit_window_open_addressbook (window, NULL);
2112 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2113 gboolean show_toolbar)
2115 ModestWindowPrivate *parent_priv;
2117 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2118 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2120 /* FIXME: we can not just use the code of
2121 modest_msg_edit_window_setup_toolbar because it has a
2122 mixture of both initialization and creation code. */
2125 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2127 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2131 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2132 TnyHeaderFlags priority_flags)
2134 ModestMsgEditWindowPrivate *priv;
2135 ModestWindowPrivate *parent_priv;
2137 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2139 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2140 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2141 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2143 if (priv->priority_flags != priority_flags) {
2144 GtkAction *priority_action = NULL;
2146 priv->priority_flags = priority_flags;
2148 switch (priority_flags) {
2149 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2150 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2151 gtk_widget_show (priv->priority_icon);
2152 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2153 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2155 case TNY_HEADER_FLAG_LOW_PRIORITY:
2156 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2157 gtk_widget_show (priv->priority_icon);
2158 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2159 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2162 gtk_widget_hide (priv->priority_icon);
2163 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2164 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2167 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2168 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2173 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2176 ModestMsgEditWindowPrivate *priv;
2177 ModestWindowPrivate *parent_priv;
2178 gint current_format;
2180 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2182 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2183 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2185 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2186 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2188 if (current_format != file_format) {
2189 switch (file_format) {
2190 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2191 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2193 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2197 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2198 response = gtk_dialog_run (GTK_DIALOG (dialog));
2199 gtk_widget_destroy (dialog);
2200 if (response == GTK_RESPONSE_OK) {
2201 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2203 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2204 toggle_action_set_active_block_notify (action, TRUE);
2209 update_dimmed (window);
2214 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2217 ModestMsgEditWindowPrivate *priv;
2218 WPTextBufferFormat oldfmt, fmt;
2219 gint old_position = 0;
2223 GdkColor *color = NULL;
2224 gboolean bold, bold_set, italic, italic_set;
2225 gboolean underline, underline_set;
2226 gboolean strikethrough, strikethrough_set;
2227 gboolean position_set;
2228 gboolean font_size_set, font_set, color_set;
2231 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2232 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2234 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2236 /* First we get the currently selected font information */
2237 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2238 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2240 switch (oldfmt.text_position) {
2241 case TEXT_POSITION_NORMAL:
2244 case TEXT_POSITION_SUPERSCRIPT:
2252 g_object_set (G_OBJECT (dialog),
2253 "bold", oldfmt.bold != FALSE,
2254 "bold-set", !oldfmt.cs.bold,
2255 "underline", oldfmt.underline != FALSE,
2256 "underline-set", !oldfmt.cs.underline,
2257 "italic", oldfmt.italic != FALSE,
2258 "italic-set", !oldfmt.cs.italic,
2259 "strikethrough", oldfmt.strikethrough != FALSE,
2260 "strikethrough-set", !oldfmt.cs.strikethrough,
2261 "color", &oldfmt.color,
2262 "color-set", !oldfmt.cs.color,
2263 "size", wp_font_size[oldfmt.font_size],
2264 "size-set", !oldfmt.cs.font_size,
2265 "position", old_position,
2266 "position-set", !oldfmt.cs.text_position,
2267 "family", wp_get_font_name (oldfmt.font),
2268 "family-set", !oldfmt.cs.font,
2271 gtk_widget_show_all (dialog);
2272 response = gtk_dialog_run (GTK_DIALOG (dialog));
2273 if (response == GTK_RESPONSE_OK) {
2275 g_object_get( dialog,
2277 "bold-set", &bold_set,
2278 "underline", &underline,
2279 "underline-set", &underline_set,
2281 "italic-set", &italic_set,
2282 "strikethrough", &strikethrough,
2283 "strikethrough-set", &strikethrough_set,
2285 "color-set", &color_set,
2287 "size-set", &font_size_set,
2288 "family", &font_name,
2289 "family-set", &font_set,
2290 "position", &position,
2291 "position-set", &position_set,
2296 if (response == GTK_RESPONSE_OK) {
2297 memset(&fmt, 0, sizeof(fmt));
2303 fmt.italic = italic;
2304 fmt.cs.italic = TRUE;
2306 if (underline_set) {
2307 fmt.underline = underline;
2308 fmt.cs.underline = TRUE;
2310 if (strikethrough_set) {
2311 fmt.strikethrough = strikethrough;
2312 fmt.cs.strikethrough = TRUE;
2317 ? TEXT_POSITION_NORMAL
2318 : ( ( position == 1 )
2319 ? TEXT_POSITION_SUPERSCRIPT
2320 : TEXT_POSITION_SUBSCRIPT );
2321 fmt.cs.text_position = TRUE;
2325 fmt.cs.color = TRUE;
2328 fmt.font = wp_get_font_index(font_name,
2333 if (font_size_set) {
2334 fmt.font_size = wp_get_font_size_index(
2335 font_size, DEFAULT_FONT_SIZE);
2336 fmt.cs.font_size = TRUE;
2338 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2340 gtk_widget_destroy (dialog);
2342 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2346 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2348 ModestMsgEditWindowPrivate *priv;
2350 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2351 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2353 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2355 update_dimmed (window);
2360 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2362 ModestMsgEditWindowPrivate *priv;
2364 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2365 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2367 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2369 update_dimmed (window);
2374 update_dimmed (ModestMsgEditWindow *window)
2376 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2377 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2381 gboolean editor_focused;
2383 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2384 editor_focused = gtk_widget_is_focus (priv->msg_body);
2386 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2387 gtk_action_set_sensitive (action, rich_text && editor_focused);
2388 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2389 gtk_action_set_sensitive (action, rich_text && editor_focused);
2390 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2391 gtk_action_set_sensitive (action, rich_text && editor_focused);
2392 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2393 gtk_action_set_sensitive (action, rich_text && editor_focused);
2394 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2395 gtk_action_set_sensitive (action, rich_text && editor_focused);
2396 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2397 gtk_action_set_sensitive (action, rich_text && editor_focused);
2398 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2399 gtk_action_set_sensitive (action, rich_text && editor_focused);
2400 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2401 gtk_action_set_sensitive (action, rich_text && editor_focused);
2402 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2403 gtk_action_set_sensitive (action, rich_text && editor_focused);
2404 widget = priv->font_color_button;
2405 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2406 widget = priv->font_size_toolitem;
2407 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2408 widget = priv->font_face_toolitem;
2409 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2413 setup_insensitive_handlers (ModestMsgEditWindow *window)
2415 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2416 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2419 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2420 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2421 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2422 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2424 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2425 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2426 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2427 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2428 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2429 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2430 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2431 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2432 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2433 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2434 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2435 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2436 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2437 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2438 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2439 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2440 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2441 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2442 widget = priv->font_color_button;
2443 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2444 widget = priv->font_size_toolitem;
2445 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2446 widget = priv->font_face_toolitem;
2447 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2449 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2450 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (remove_attachment_insensitive_press), window);
2451 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2452 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (zoom_insensitive_press), window);
2454 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2455 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (paste_insensitive_press), window);
2456 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2457 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (copy_insensitive_press), window);
2461 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2463 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2466 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2467 gtk_action_set_sensitive (action, can_undo);
2471 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2473 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2476 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/RedoMenu");
2477 gtk_action_set_sensitive (action, can_redo);
2481 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2484 GtkTextIter match_start, match_end;
2486 if (image_id == NULL)
2489 gtk_text_buffer_get_start_iter (buffer, &iter);
2491 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2492 GSList *tags = gtk_text_iter_get_tags (&match_start);
2494 for (node = tags; node != NULL; node = g_slist_next (node)) {
2495 GtkTextTag *tag = (GtkTextTag *) node->data;
2496 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2497 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2498 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2500 offset = gtk_text_iter_get_offset (&match_start);
2501 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2502 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2506 gtk_text_iter_forward_char (&iter);
2511 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2513 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2514 GtkTextIter real_start, real_end;
2515 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2517 if (gtk_text_iter_compare (start, end) > 0) {
2521 real_start = *start;
2525 GSList *tags = gtk_text_iter_get_tags (&real_start);
2527 for (node = tags; node != NULL; node = g_slist_next (node)) {
2528 GtkTextTag *tag = (GtkTextTag *) node->data;
2529 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2530 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2532 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2534 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2537 } while (gtk_text_iter_forward_char (&real_start)&&
2538 (gtk_text_iter_compare (&real_start, &real_end)<=0));
2542 msg_body_focus (GtkWidget *focus,
2543 GdkEventFocus *event,
2547 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2552 recpt_field_changed (GtkTextBuffer *buffer,
2553 ModestMsgEditWindow *editor)
2555 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2556 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2557 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2558 gboolean dim = FALSE;
2561 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2562 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2563 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2565 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2566 gtk_text_buffer_get_char_count (cc_buffer) +
2567 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2569 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2570 gtk_action_set_sensitive (action, !dim);
2571 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2572 gtk_action_set_sensitive (action, !dim);
2576 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2578 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2582 zoom_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2584 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2588 remove_attachment_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2590 ModestWindowPrivate *parent_priv;
2591 ModestMsgEditWindowPrivate *priv;
2592 GList *selected_attachments = NULL;
2593 gint n_att_selected = 0;
2595 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2596 parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2598 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2599 n_att_selected = g_list_length (selected_attachments);
2600 g_list_free (selected_attachments);
2602 if (n_att_selected > 1)
2603 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unable_to_display_more"));
2604 else if (n_att_selected == 0)
2605 hildon_banner_show_information (NULL, NULL, _("TODO: select one attachment"));
2607 hildon_banner_show_information (NULL, NULL, _("mail_ib_unable_to_purge_attachments"));
2611 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2613 gboolean rich_text, editor_focused;
2615 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2616 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2617 editor_focused = gtk_widget_is_focus (priv->msg_body);
2620 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2621 else if (!editor_focused)
2622 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2626 reset_modified (ModestMsgEditWindow *editor)
2628 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2629 GtkTextBuffer *buffer;
2631 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2632 gtk_text_buffer_set_modified (buffer, FALSE);
2633 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2634 gtk_text_buffer_set_modified (buffer, FALSE);
2635 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2636 gtk_text_buffer_set_modified (buffer, FALSE);
2637 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2641 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2643 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2644 GtkTextBuffer *buffer;
2646 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2647 if (gtk_text_buffer_get_modified (buffer))
2649 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2650 if (gtk_text_buffer_get_modified (buffer))
2652 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2653 if (gtk_text_buffer_get_modified (buffer))
2655 if (gtk_text_buffer_get_modified (priv->text_buffer))
2662 modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
2664 ModestMsgEditWindowPrivate *priv = NULL;
2666 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2667 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2669 /* check if there's no recipient added */
2670 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2671 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2672 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2673 /* no recipient contents, then select contacts */
2674 modest_msg_edit_window_open_addressbook (window, NULL);
2678 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
2680 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
2682 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
2685 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2692 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2693 ModestMsgEditWindow *window)
2695 modest_msg_edit_window_attach_file (window);
2699 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2701 ModestMsgEditWindow *window)
2703 ModestWindowPrivate *parent_priv;
2704 ModestMsgEditWindowPrivate *priv;
2706 gboolean has_selection;
2708 GList *selected_attachments = NULL;
2709 gint n_att_selected = 0;
2711 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2712 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2713 has_selection = gtk_clipboard_wait_for_targets (clipboard, NULL, NULL);
2714 focused = gtk_window_get_focus (GTK_WINDOW (window));
2716 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2717 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2718 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2719 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2721 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2722 n_att_selected = g_list_length (selected_attachments);
2723 g_list_free (selected_attachments);
2725 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2726 gtk_action_set_sensitive (action, n_att_selected == 1);
2728 update_paste_dimming (window);
2732 update_window_title (ModestMsgEditWindow *window)
2734 ModestMsgEditWindowPrivate *priv = NULL;
2735 const gchar *subject;
2737 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2738 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2739 if (subject == NULL || subject[0] == '\0')
2740 subject = _("mail_va_new_email");
2742 gtk_window_set_title (GTK_WINDOW (window), subject);
2747 subject_field_changed (GtkEditable *editable,
2748 ModestMsgEditWindow *window)
2750 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2751 update_window_title (window);
2752 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2756 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2759 ModestMsgEditWindowPrivate *priv = NULL;
2761 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2762 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2764 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2766 gtk_widget_show_all (priv->find_toolbar);
2767 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2769 gtk_widget_hide_all (priv->find_toolbar);
2770 gtk_widget_grab_focus (priv->msg_body);
2776 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2778 GtkTextIter *match_start,
2779 GtkTextIter *match_end)
2781 GtkTextIter end_iter;
2782 gchar *str_casefold;
2785 gchar *range_casefold;
2788 gboolean result = FALSE;
2795 gtk_text_iter_forward_to_end (&end_iter);
2797 str_casefold = g_utf8_casefold (str, -1);
2798 str_chars_n = strlen (str);
2800 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2801 range_casefold = g_utf8_casefold (range_text, -1);
2802 range_chars_n = strlen (range_casefold);
2804 if (range_chars_n < str_chars_n) {
2805 g_free (str_casefold);
2806 g_free (range_text);
2807 g_free (range_casefold);
2811 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2812 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2813 if (!g_utf8_collate (range_subtext, str_casefold)) {
2814 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2816 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2817 match_start, match_end, NULL);
2818 g_free (found_text);
2820 g_free (range_subtext);
2824 g_free (str_casefold);
2825 g_free (range_text);
2826 g_free (range_casefold);
2833 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2834 ModestMsgEditWindow *window)
2836 gchar *current_search = NULL;
2837 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2839 GtkTextIter selection_start, selection_end;
2840 GtkTextIter match_start, match_end;
2841 gboolean continue_search = FALSE;
2843 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2844 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2845 g_free (current_search);
2846 g_free (priv->last_search);
2847 priv->last_search = NULL;
2848 /* Information banner about empty search */
2849 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2853 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2854 continue_search = TRUE;
2856 g_free (priv->last_search);
2857 priv->last_search = g_strdup (current_search);
2860 if (continue_search) {
2861 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2862 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2863 &match_start, &match_end);
2865 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2867 GtkTextIter buffer_start;
2868 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2869 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2870 &match_start, &match_end);
2872 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2875 /* Mark as selected the string found in search */
2877 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2878 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2880 g_free (priv->last_search);
2881 priv->last_search = NULL;
2883 g_free (current_search);
2887 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2888 ModestMsgEditWindow *window)
2890 GtkToggleAction *toggle;
2891 ModestWindowPrivate *parent_priv;
2892 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2894 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2895 gtk_toggle_action_set_active (toggle, FALSE);
2900 update_paste_dimming (ModestMsgEditWindow *window)
2902 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2903 GtkAction *action = NULL;
2904 GtkClipboard *clipboard = NULL;
2908 focused = gtk_window_get_focus (GTK_WINDOW (window));
2910 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2911 active = gtk_clipboard_wait_is_text_available (clipboard);
2914 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2918 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2919 gtk_action_set_sensitive (action, active);
2924 paste_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2926 GtkWidget *focused = gtk_window_get_focus (GTK_WINDOW (editor));
2928 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2929 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_unable_to_paste_here"));
2931 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ecoc_ib_edwin_nothing_to_paste"));
2936 copy_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2938 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_unable_to_copy"));
2944 modest_msg_edit_window_system_clipboard_owner_change (GtkClipboard *clipboard,
2946 ModestMsgEditWindow *window)
2948 update_paste_dimming (window);
2952 update_select_all_dimming (ModestMsgEditWindow *window)
2955 gboolean dimmed = FALSE;
2957 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2959 focused = gtk_window_get_focus (GTK_WINDOW (window));
2960 if (GTK_IS_ENTRY (focused)) {
2961 const gchar *current_text;
2962 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
2963 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
2964 } else if (GTK_IS_TEXT_VIEW (focused)) {
2965 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
2966 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
2967 } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
2970 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
2971 gtk_action_set_sensitive (action, !dimmed);
2975 update_zoom_dimming (ModestMsgEditWindow *window)
2978 gboolean dimmed = FALSE;
2980 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2982 focused = gtk_window_get_focus (GTK_WINDOW (window));
2983 dimmed = ! WP_IS_TEXT_VIEW (focused);
2984 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2985 gtk_action_set_sensitive (action, !dimmed);
2989 edit_menu_activated (GtkAction *action,
2992 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2994 update_select_all_dimming (window);
2997 view_menu_activated (GtkAction *action,
3000 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3002 update_zoom_dimming (window);
3006 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3008 ModestMsgEditWindowPrivate *priv;
3010 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3015 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3018 ModestMsgEditWindowPrivate *priv;
3020 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3026 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3029 ModestMsgEditWindowPrivate *priv;
3030 TnyHeader *header = NULL;
3032 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3033 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3035 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3036 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3038 if (priv->draft_msg != NULL) {
3039 header = tny_msg_get_header (priv->draft_msg);
3040 if (TNY_IS_HEADER (header)) {
3041 modest_window_mgr_unregister_header (mgr, header);
3043 g_object_unref (priv->draft_msg);
3046 if (draft != NULL) {
3047 g_object_ref (draft);
3048 header = tny_msg_get_header (draft);
3049 if (TNY_IS_HEADER (header))
3050 modest_window_mgr_register_header (mgr, header);
3053 priv->draft_msg = draft;