1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
41 #include <modest-account-mgr.h>
42 #include <modest-account-mgr-helpers.h>
44 #include <widgets/modest-msg-edit-window.h>
45 #include <widgets/modest-combo-box.h>
46 #include <widgets/modest-recpt-editor.h>
47 #include <widgets/modest-attachments-view.h>
49 #include <modest-runtime.h>
51 #include "modest-platform.h"
52 #include "modest-icon-names.h"
53 #include "modest-widget-memory.h"
54 #include "modest-window-priv.h"
55 #include "modest-mail-operation.h"
56 #include "modest-tny-platform-factory.h"
57 #include "modest-tny-msg.h"
58 #include "modest-address-book.h"
59 #include "modest-text-utils.h"
60 #include <tny-simple-list.h>
61 #include <wptextview.h>
62 #include <wptextbuffer.h>
63 #include "modest-scroll-area.h"
65 #include "modest-hildon-includes.h"
66 #ifdef MODEST_HAVE_HILDON0_WIDGETS
67 #include <hildon-widgets/hildon-color-chooser.h>
69 #include "widgets/modest-msg-edit-window-ui.h"
70 #ifdef MODEST_HAVE_HILDON0_WIDGETS
71 #include <libgnomevfs/gnome-vfs-mime-utils.h>
73 #include <libgnomevfs/gnome-vfs-mime.h>
75 #include "modest-maemo-utils.h"
78 #define DEFAULT_FONT_SIZE 3
79 #define DEFAULT_FONT 2
80 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
81 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
82 #define DEFAULT_MAIN_VBOX_SPACING 6
83 #define SUBJECT_MAX_LENGTH 1000
84 #define IMAGE_MAX_WIDTH 640
86 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
87 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
88 static void modest_msg_edit_window_finalize (GObject *obj);
90 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
91 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
92 static void send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
93 static void style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
94 static void remove_attachment_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
95 static void zoom_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
96 static void paste_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
97 static void setup_insensitive_handlers (ModestMsgEditWindow *editor);
98 static void reset_modified (ModestMsgEditWindow *editor);
100 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
101 static void text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata);
102 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
103 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
104 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
105 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
107 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
109 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
111 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
112 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
113 GdkEventWindowState *event,
115 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
116 ModestRecptEditor *editor);
117 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
118 ModestMsgEditWindow *window);
120 /* ModestWindow methods implementation */
121 static void modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom);
122 static gdouble modest_msg_edit_window_get_zoom (ModestWindow *window);
123 static gboolean modest_msg_edit_window_zoom_minus (ModestWindow *window);
124 static gboolean modest_msg_edit_window_zoom_plus (ModestWindow *window);
125 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
126 gboolean show_toolbar);
127 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
129 ModestMsgEditWindow *window);
130 static void modest_msg_edit_window_system_clipboard_owner_change (GtkClipboard *clipboard,
132 ModestMsgEditWindow *window);
133 static void update_window_title (ModestMsgEditWindow *window);
134 static void update_dimmed (ModestMsgEditWindow *window);
135 static void update_paste_dimming (ModestMsgEditWindow *window);
136 static void update_select_all_dimming (ModestMsgEditWindow *window);
137 static void update_zoom_dimming (ModestMsgEditWindow *window);
140 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
141 ModestMsgEditWindow *window);
142 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
143 ModestMsgEditWindow *window);
144 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
146 GtkTextIter *match_start,
147 GtkTextIter *match_end);
151 /* static gboolean */
152 /* on_key_pressed (GtkWidget *self, */
153 /* GdkEventKey *event, */
154 /* gpointer user_data); */
156 static void edit_menu_activated (GtkAction *action,
158 static void view_menu_activated (GtkAction *action,
161 /* list my signals */
168 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
169 struct _ModestMsgEditWindowPrivate {
171 GtkWidget *header_box;
173 ModestPairList *from_field_protos;
174 GtkWidget *from_field;
178 GtkWidget *bcc_field;
179 GtkWidget *subject_field;
180 GtkWidget *attachments_view;
181 GtkWidget *priority_icon;
182 GtkWidget *add_attachment_button;
184 GtkWidget *cc_caption;
185 GtkWidget *bcc_caption;
186 GtkWidget *attachments_caption;
188 GtkTextBuffer *text_buffer;
190 GtkWidget *font_size_toolitem;
191 GtkWidget *font_face_toolitem;
192 GtkWidget *font_color_button;
193 GSList *font_items_group;
194 GtkWidget *font_tool_button_label;
195 GSList *size_items_group;
196 GtkWidget *size_tool_button_label;
198 GtkWidget *find_toolbar;
202 GtkWidget *scroll_area;
207 TnyHeaderFlags priority_flags;
211 gulong clipboard_change_handler_id;
212 gulong system_clipboard_change_handler_id;
218 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
219 MODEST_TYPE_MSG_EDIT_WINDOW, \
220 ModestMsgEditWindowPrivate))
222 static GtkWindowClass *parent_class = NULL;
224 /* uncomment the following if you have defined any signals */
225 /* static guint signals[LAST_SIGNAL] = {0}; */
228 modest_msg_edit_window_get_type (void)
230 static GType my_type = 0;
232 static const GTypeInfo my_info = {
233 sizeof(ModestMsgEditWindowClass),
234 NULL, /* base init */
235 NULL, /* base finalize */
236 (GClassInitFunc) modest_msg_edit_window_class_init,
237 NULL, /* class finalize */
238 NULL, /* class data */
239 sizeof(ModestMsgEditWindow),
241 (GInstanceInitFunc) modest_msg_edit_window_init,
244 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
245 "ModestMsgEditWindow",
248 wp_text_buffer_library_init ();
254 save_state (ModestWindow *self)
256 modest_widget_memory_save (modest_runtime_get_conf(),
257 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
262 restore_settings (ModestMsgEditWindow *self)
264 modest_widget_memory_restore (modest_runtime_get_conf(),
265 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
270 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
272 GObjectClass *gobject_class;
273 ModestWindowClass *modest_window_class;
274 gobject_class = (GObjectClass*) klass;
275 modest_window_class = (ModestWindowClass*) klass;
277 parent_class = g_type_class_peek_parent (klass);
278 gobject_class->finalize = modest_msg_edit_window_finalize;
280 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
281 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
282 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
283 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
284 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
285 modest_window_class->save_state_func = save_state;
287 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
293 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
295 ModestMsgEditWindowPrivate *priv;
296 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
298 priv->msg_body = NULL;
299 priv->from_field = NULL;
300 priv->to_field = NULL;
301 priv->cc_field = NULL;
302 priv->bcc_field = NULL;
303 priv->subject_field = NULL;
304 priv->attachments = NULL;
306 priv->zoom_level = 1.0;
308 priv->cc_caption = NULL;
309 priv->bcc_caption = NULL;
311 priv->priority_flags = 0;
313 priv->find_toolbar = NULL;
314 priv->last_search = NULL;
316 priv->draft_msg = NULL;
317 priv->clipboard_change_handler_id = 0;
318 priv->system_clipboard_change_handler_id = 0;
323 /* FIXME: this is a dup from the one in gtk/ */
326 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
328 static ModestPairList*
329 get_transports (void)
331 GSList *transports = NULL;
333 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
334 GSList *accounts = modest_account_mgr_account_names (account_mgr,
335 TRUE /* only enabled accounts. */);
337 GSList *cursor = accounts;
339 gchar *account_name = cursor->data;
340 gchar *from_string = NULL;
342 from_string = modest_account_mgr_get_from_string (account_mgr,
346 if (from_string && account_name) {
347 gchar *name = account_name;
348 ModestPair *pair = modest_pair_new ((gpointer) name,
349 (gpointer) from_string , TRUE);
350 transports = g_slist_prepend (transports, pair);
353 cursor = cursor->next;
355 g_slist_free (accounts); /* only free the accounts, not the elements,
356 * because they are used in the pairlist */
362 init_window (ModestMsgEditWindow *obj)
364 GtkWidget *from_caption, *to_caption, *subject_caption;
365 GtkWidget *main_vbox;
366 ModestMsgEditWindowPrivate *priv;
368 GtkSizeGroup *size_group;
370 GtkWidget *subject_box;
371 GtkWidget *attachment_icon;
372 GtkWidget *window_box;
374 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
376 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
378 /* Note: This ModestPairList* must exist for as long as the combo
379 * that uses it, because the ModestComboBox uses the ID opaquely,
380 * so it can't know how to manage its memory. */
381 priv->from_field_protos = get_transports ();
383 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
385 priv->to_field = modest_recpt_editor_new ();
386 priv->cc_field = modest_recpt_editor_new ();
387 priv->bcc_field = modest_recpt_editor_new ();
388 subject_box = gtk_hbox_new (FALSE, 0);
389 priv->priority_icon = gtk_image_new ();
390 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
391 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
392 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
393 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
394 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
395 priv->add_attachment_button = gtk_button_new ();
396 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
397 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
398 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
399 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
400 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
401 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
402 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
403 priv->attachments_view = modest_attachments_view_new (NULL);
405 priv->header_box = gtk_vbox_new (FALSE, 0);
407 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
408 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
409 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
410 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
411 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
412 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
413 g_object_unref (size_group);
415 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
416 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
417 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
418 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
419 gtk_size_group_add_widget (size_group, priv->subject_field);
420 gtk_size_group_add_widget (size_group, priv->attachments_view);
421 g_object_unref (size_group);
423 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
424 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
425 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
426 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
427 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
428 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
429 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
432 priv->msg_body = wp_text_view_new ();
433 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
434 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
435 g_object_set (priv->text_buffer, "font_scale", 1.0, NULL);
436 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
437 /* gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
438 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
440 priv->find_toolbar = hildon_find_toolbar_new (NULL);
441 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
443 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
445 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
446 G_CALLBACK (text_buffer_refresh_attributes), obj);
447 g_signal_connect (G_OBJECT (priv->text_buffer), "delete-range",
448 G_CALLBACK (text_buffer_delete_range), obj);
449 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
450 G_CALLBACK (text_buffer_can_undo), obj);
451 g_signal_connect (G_OBJECT (obj), "window-state-event",
452 G_CALLBACK (modest_msg_edit_window_window_state_event),
454 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
455 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
456 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
457 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
458 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
459 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
461 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
462 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
464 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
465 G_CALLBACK (msg_body_focus), obj);
466 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
467 G_CALLBACK (msg_body_focus), obj);
468 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
469 "changed", G_CALLBACK (recpt_field_changed), obj);
470 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
471 "changed", G_CALLBACK (recpt_field_changed), obj);
472 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
473 "changed", G_CALLBACK (recpt_field_changed), obj);
474 recpt_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
475 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
477 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
478 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
480 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
481 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
482 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
484 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
486 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
487 frame = gtk_frame_new (NULL);
488 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
490 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
491 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
492 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
494 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL)) {
495 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
496 gtk_widget_hide (priv->cc_caption);
498 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL)) {
499 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
500 gtk_widget_hide (priv->bcc_caption);
503 window_box = gtk_vbox_new (FALSE, 0);
504 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
505 gtk_box_pack_end (GTK_BOX (window_box), priv->find_toolbar, FALSE, FALSE, 0);
506 gtk_container_add (GTK_CONTAINER(obj), window_box);
507 priv->scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
508 gtk_container_add (GTK_CONTAINER (frame), priv->scroll_area);
511 TODO: scroll_area was never instantiated.
512 Stop building without warnings-as-errors. murrayc.
513 gtk_container_set_focus_vadjustment (GTK_CONTAINER (scroll_area),
514 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
517 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
518 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
519 priv->system_clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
520 G_CALLBACK (modest_msg_edit_window_system_clipboard_owner_change), obj);
526 modest_msg_edit_window_finalize (GObject *obj)
528 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
530 if (priv->clipboard_change_handler_id > 0) {
531 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), priv->clipboard_change_handler_id);
532 priv->clipboard_change_handler_id = 0;
535 if (priv->system_clipboard_change_handler_id > 0) {
536 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
537 priv->system_clipboard_change_handler_id);
538 priv->system_clipboard_change_handler_id = 0;
541 if (priv->draft_msg != NULL) {
542 g_object_unref (priv->draft_msg);
543 priv->draft_msg = NULL;
546 /* This had to stay alive for as long as the combobox that used it: */
547 modest_pair_list_free (priv->from_field_protos);
549 G_OBJECT_CLASS(parent_class)->finalize (obj);
553 menubar_to_menu (GtkUIManager *ui_manager)
555 GtkWidget *main_menu;
559 /* Create new main menu */
560 main_menu = gtk_menu_new();
562 /* Get the menubar from the UI manager */
563 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
565 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
569 menu = GTK_WIDGET (iter->data);
570 gtk_widget_reparent(menu, main_menu);
572 iter = g_list_next (iter);
579 set_msg (ModestMsgEditWindow *self, TnyMsg *msg)
582 const gchar *to, *cc, *bcc, *subject;
584 ModestMsgEditWindowPrivate *priv;
586 TnyHeaderFlags priority_flags;
588 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
589 g_return_if_fail (TNY_IS_MSG (msg));
591 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
593 header = tny_msg_get_header (msg);
594 to = tny_header_get_to (header);
595 cc = tny_header_get_cc (header);
596 bcc = tny_header_get_bcc (header);
597 subject = tny_header_get_subject (header);
598 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
601 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
603 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
604 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
605 gtk_widget_show (priv->cc_caption);
606 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
607 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
608 gtk_widget_hide (priv->cc_caption);
611 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
612 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
613 gtk_widget_show (priv->bcc_caption);
614 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
615 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
616 gtk_widget_hide (priv->bcc_caption);
619 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
620 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
623 update_window_title (self);
625 /* gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
626 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
627 body = modest_tny_msg_get_body (msg, TRUE);
629 if ((body == NULL)||(body[0] == '\0')) {
631 body = modest_text_utils_convert_to_html ("");
633 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
634 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
637 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
640 /* Get the default format required from configuration */
641 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
642 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
645 /* Set the default focus depending on having already a To: field or not */
646 if ((!to)||(*to == '\0')) {
647 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
649 gtk_widget_grab_focus (priv->msg_body);
652 /* TODO: lower priority, select in the From: combo to the
653 value that comes from msg <- not sure, should it be
656 /* Add attachments to the view */
657 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
658 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
659 if (priv->attachments == NULL) {
660 gtk_widget_hide (priv->attachments_caption);
662 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
663 gtk_widget_show_all (priv->attachments_caption);
666 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
667 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
669 reset_modified (self);
671 update_dimmed (self);
672 text_buffer_can_undo (priv->text_buffer, FALSE, self);
674 priv->draft_msg = g_object_ref(msg);
678 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
681 GList *item_children, *node;
682 GtkWidget *bin_child;
684 bin_child = gtk_bin_get_child (GTK_BIN(item));
686 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
688 for (node = item_children; node != NULL; node = g_list_next (node)) {
689 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
690 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
693 g_list_free (item_children);
697 menu_tool_button_dont_expand (GtkMenuToolButton *item)
700 GList *item_children, *node;
702 box = gtk_bin_get_child (GTK_BIN (item));
703 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
704 item_children = gtk_container_get_children (GTK_CONTAINER (box));
706 for (node = item_children; node != NULL; node = g_list_next (node)) {
707 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
708 if (GTK_IS_TOGGLE_BUTTON (node->data))
709 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
710 else if (GTK_IS_BUTTON (node->data))
711 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
713 g_list_free (item_children);
718 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
720 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
721 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
722 GtkWidget *placeholder;
723 GtkWidget *tool_item;
728 GtkWidget *sizes_menu;
729 GtkWidget *fonts_menu;
730 GSList *radio_group = NULL;
735 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
736 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
738 /* should we hide the toolbar? */
739 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
740 gtk_widget_hide (parent_priv->toolbar);
742 /* Font color placeholder */
743 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
744 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
747 tool_item = GTK_WIDGET (gtk_tool_item_new ());
748 priv->font_color_button = hildon_color_button_new ();
749 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
750 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
751 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
752 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
753 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
754 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
755 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
757 /* Font size and face placeholder */
758 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
759 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
761 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
762 priv->size_tool_button_label = gtk_label_new (NULL);
763 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
764 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
765 size_text,"</span>", NULL);
766 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
768 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
769 sizes_menu = gtk_menu_new ();
770 priv->size_items_group = NULL;
772 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
773 GtkWidget *size_menu_item;
775 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
776 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
777 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
778 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
779 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
780 gtk_widget_show (size_menu_item);
782 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
786 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
787 GtkWidget *item = (GtkWidget *) node->data;
788 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
792 priv->size_items_group = g_slist_reverse (priv->size_items_group);
793 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
794 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
795 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
796 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
797 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
798 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
799 priv->font_size_toolitem = tool_item;
802 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
803 priv->font_tool_button_label = gtk_label_new (NULL);
804 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
805 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
807 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
808 fonts_menu = gtk_menu_new ();
809 priv->font_items_group = NULL;
811 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
812 GtkWidget *font_menu_item;
813 GtkWidget *child_label;
815 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
816 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
817 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
818 wp_get_font_name (font_index), "</span>", NULL);
819 gtk_label_set_markup (GTK_LABEL (child_label), markup);
822 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
823 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
824 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
825 gtk_widget_show (font_menu_item);
827 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
830 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
831 GtkWidget *item = (GtkWidget *) node->data;
832 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
835 priv->font_items_group = g_slist_reverse (priv->font_items_group);
836 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
837 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
838 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
839 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
840 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
841 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
842 priv->font_face_toolitem = tool_item;
844 /* Set expand and homogeneous for remaining items */
845 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
846 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
847 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
848 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
849 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
850 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
851 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
852 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
853 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
861 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name)
864 ModestWindowPrivate *parent_priv;
865 ModestMsgEditWindowPrivate *priv;
866 GtkActionGroup *action_group;
867 GError *error = NULL;
868 GdkPixbuf *window_icon = NULL;
871 gboolean prefer_formatted;
873 ModestPair *account_pair = NULL;
875 g_return_val_if_fail (msg, NULL);
876 g_return_val_if_fail (account_name, NULL);
878 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
880 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
881 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
883 parent_priv->ui_manager = gtk_ui_manager_new();
884 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
885 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
887 /* Add common actions */
888 gtk_action_group_add_actions (action_group,
889 modest_msg_edit_action_entries,
890 G_N_ELEMENTS (modest_msg_edit_action_entries),
892 gtk_action_group_add_toggle_actions (action_group,
893 modest_msg_edit_toggle_action_entries,
894 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
896 gtk_action_group_add_radio_actions (action_group,
897 modest_msg_edit_alignment_radio_action_entries,
898 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
900 G_CALLBACK (modest_ui_actions_on_change_justify),
902 gtk_action_group_add_radio_actions (action_group,
903 modest_msg_edit_zoom_action_entries,
904 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
906 G_CALLBACK (modest_ui_actions_on_change_zoom),
908 gtk_action_group_add_radio_actions (action_group,
909 modest_msg_edit_priority_action_entries,
910 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
912 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
914 gtk_action_group_add_radio_actions (action_group,
915 modest_msg_edit_file_format_action_entries,
916 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
917 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
918 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
920 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
921 g_object_unref (action_group);
923 /* Load the UI definition */
924 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
927 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
928 g_clear_error (&error);
931 /* Add accelerators */
932 gtk_window_add_accel_group (GTK_WINDOW (obj),
933 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
936 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
937 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
940 init_window (MODEST_MSG_EDIT_WINDOW(obj));
942 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
944 gtk_window_set_icon_from_file (GTK_WINDOW(obj), MODEST_APP_ICON, NULL);
946 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
948 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
950 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
952 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
953 if (account_pair != NULL)
954 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
956 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg);
958 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
960 /* Set window icon */
961 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
962 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
964 /* Dim at start clipboard actions */
965 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
966 gtk_action_set_sensitive (action, FALSE);
967 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
968 gtk_action_set_sensitive (action, FALSE);
969 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
970 gtk_action_set_sensitive (action, FALSE);
972 /* Update select all */
973 update_select_all_dimming (MODEST_MSG_EDIT_WINDOW (obj));
974 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu");
975 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (edit_menu_activated), obj);
976 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu");
977 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (view_menu_activated), obj);
979 /* set initial state of cc and bcc */
980 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
981 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
982 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
983 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
984 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
985 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
987 /* Setup the file format */
988 conf = modest_runtime_get_conf ();
989 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
991 g_clear_error (&error);
992 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
994 file_format = (prefer_formatted) ?
995 MODEST_FILE_FORMAT_FORMATTED_TEXT :
996 MODEST_FILE_FORMAT_PLAIN_TEXT;
997 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
999 update_paste_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1001 return (ModestWindow*) obj;
1005 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1007 GString **string_buffer = (GString **) user_data;
1009 *string_buffer = g_string_append (*string_buffer, buffer);
1015 * @result: A new string which should be freed with g_free().
1018 get_formatted_data (ModestMsgEditWindow *edit_window)
1020 ModestMsgEditWindowPrivate *priv;
1021 GString *string_buffer = g_string_new ("");
1023 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1025 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1027 return g_string_free (string_buffer, FALSE);
1032 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1035 const gchar *account_name;
1036 ModestMsgEditWindowPrivate *priv;
1038 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1040 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1042 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1043 g_return_val_if_fail (account_name, NULL);
1046 /* don't free these (except from) */
1047 data = g_slice_new0 (MsgData);
1048 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1050 data->account_name = g_strdup (account_name);
1051 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1052 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1053 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1054 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1055 if (priv->draft_msg) {
1056 data->draft_msg = g_object_ref (priv->draft_msg);
1058 data->draft_msg = NULL;
1061 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1063 gtk_text_buffer_get_bounds (buf, &b, &e);
1064 data->plain_body = g_strdup (gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE)); /* returns a copy */
1066 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1067 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1069 data->html_body = NULL;
1071 data->attachments = priv->attachments; /* TODO: copy and free ? */
1072 data->priority_flags = priv->priority_flags;
1077 /* TODO: We must duplicate this implementation for GNOME and Maemo, but that is unwise. */
1079 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1082 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1090 g_free (data->subject);
1091 g_free (data->plain_body);
1092 g_free (data->html_body);
1093 if (data->draft_msg != NULL) {
1094 g_object_unref (data->draft_msg);
1095 data->draft_msg = NULL;
1097 g_free (data->account_name);
1099 /* TODO: Free data->attachments? */
1101 g_slice_free (MsgData, data);
1105 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1108 ModestMsgEditWindowPrivate *priv = NULL;
1109 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1111 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1113 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1115 return MODEST_MSG_EDIT_FORMAT_HTML;
1117 return MODEST_MSG_EDIT_FORMAT_TEXT;
1121 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1122 ModestMsgEditFormat format)
1124 ModestMsgEditWindowPrivate *priv;
1126 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1127 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1130 case MODEST_MSG_EDIT_FORMAT_HTML:
1131 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1133 case MODEST_MSG_EDIT_FORMAT_TEXT:
1134 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1137 g_return_if_reached ();
1141 ModestMsgEditFormatState *
1142 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1144 ModestMsgEditFormatState *format_state = NULL;
1145 ModestMsgEditWindowPrivate *priv;
1146 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1148 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1149 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1151 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1153 format_state = g_new0 (ModestMsgEditFormatState, 1);
1154 format_state->bold = buffer_format->bold&0x1;
1155 format_state->italics = buffer_format->italic&0x1;
1156 format_state->bullet = buffer_format->bullet&0x1;
1157 format_state->color = buffer_format->color;
1158 format_state->font_size = buffer_format->font_size;
1159 format_state->font_family = wp_get_font_name (buffer_format->font);
1160 format_state->justification = buffer_format->justification;
1161 g_free (buffer_format);
1163 return format_state;
1168 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1169 const ModestMsgEditFormatState *format_state)
1171 ModestMsgEditWindowPrivate *priv;
1172 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1173 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1174 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1175 g_return_if_fail (format_state != NULL);
1177 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1178 gtk_widget_grab_focus (priv->msg_body);
1179 buffer_format->bold = (format_state->bold != FALSE);
1180 buffer_format->italic = (format_state->italics != FALSE);
1181 buffer_format->color = format_state->color;
1182 buffer_format->font_size = format_state->font_size;
1183 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1184 buffer_format->justification = format_state->justification;
1185 buffer_format->bullet = format_state->bullet;
1187 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1189 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1190 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1191 buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
1192 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1193 buffer_format->cs.font = (buffer_format->font != current_format->font);
1194 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1195 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1197 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1198 if (buffer_format->cs.bold) {
1199 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1201 if (buffer_format->cs.italic) {
1202 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1204 if (buffer_format->cs.color) {
1205 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1207 if (buffer_format->cs.font_size) {
1208 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1210 if (buffer_format->cs.justification) {
1211 switch (buffer_format->justification) {
1212 case GTK_JUSTIFY_LEFT:
1213 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1215 case GTK_JUSTIFY_CENTER:
1216 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1218 case GTK_JUSTIFY_RIGHT:
1219 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1226 if (buffer_format->cs.font) {
1227 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1229 if (buffer_format->cs.bullet) {
1230 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((int)buffer_format->bullet));
1232 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1233 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1235 g_free (current_format);
1240 toggle_action_set_active_block_notify (GtkToggleAction *action,
1243 GSList *proxies = NULL;
1245 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1246 proxies != NULL; proxies = g_slist_next (proxies)) {
1247 GtkWidget *widget = (GtkWidget *) proxies->data;
1248 gtk_action_block_activate_from (GTK_ACTION (action), widget);
1251 gtk_toggle_action_set_active (action, value);
1253 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1254 proxies != NULL; proxies = g_slist_next (proxies)) {
1255 GtkWidget *widget = (GtkWidget *) proxies->data;
1256 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
1261 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1263 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1265 ModestWindowPrivate *parent_priv;
1266 ModestMsgEditWindowPrivate *priv;
1267 GtkWidget *new_size_menuitem;
1268 GtkWidget *new_font_menuitem;
1270 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1271 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1273 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1274 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1275 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1276 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1278 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1279 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1280 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1283 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1285 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1286 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1288 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1289 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1291 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1292 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1294 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1295 G_CALLBACK (modest_msg_edit_window_color_button_change),
1297 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1298 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1299 G_CALLBACK (modest_msg_edit_window_color_button_change),
1302 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1303 buffer_format->font_size))->data);
1304 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1308 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1309 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1310 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1312 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1313 G_CALLBACK (modest_msg_edit_window_size_change),
1315 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1316 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1317 G_CALLBACK (modest_msg_edit_window_size_change),
1321 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1322 buffer_format->font))->data);
1323 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1327 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1328 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1329 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1331 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1332 G_CALLBACK (modest_msg_edit_window_font_change),
1334 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1335 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1336 G_CALLBACK (modest_msg_edit_window_font_change),
1340 g_free (buffer_format);
1346 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1349 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1350 ModestMsgEditWindowPrivate *priv;
1351 GtkWidget *dialog = NULL;
1353 const GdkColor *new_color = NULL;
1355 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1356 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1358 #ifdef MODEST_HILDON_VERSION_0
1359 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1360 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1362 dialog = hildon_color_chooser_new ();
1363 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1364 #endif /*MODEST_HILDON_VERSION_0*/
1365 g_free (buffer_format);
1367 response = gtk_dialog_run (GTK_DIALOG (dialog));
1369 case GTK_RESPONSE_OK: {
1370 #ifdef MODEST_HILDON_VERSION_0
1371 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1374 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1376 #endif /*MODEST_HILDON_VERSION_0*/
1383 gtk_widget_destroy (dialog);
1385 if (new_color != NULL)
1386 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1391 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1394 ModestMsgEditWindowPrivate *priv;
1395 GtkWidget *dialog = NULL;
1397 GdkColor *old_color = NULL;
1398 const GdkColor *new_color = NULL;
1400 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1401 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1403 #ifdef MODEST_HILDON_VERSION_0
1404 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1405 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1407 dialog = hildon_color_chooser_new ();
1408 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1409 #endif /*MODEST_HILDON_VERSION_9*/
1411 response = gtk_dialog_run (GTK_DIALOG (dialog));
1413 case GTK_RESPONSE_OK: {
1414 #ifdef MODEST_HILDON_VERSION_0
1415 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1418 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1420 #endif /*MODEST_HILDON_VERSION_0*/
1426 gtk_widget_destroy (dialog);
1428 if (new_color != NULL)
1429 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1435 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1438 ModestMsgEditWindowPrivate *priv;
1439 GtkWidget *dialog = NULL;
1441 GSList *uris = NULL;
1442 GSList *uri_node = NULL;
1444 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1446 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1447 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1448 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1450 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1452 response = gtk_dialog_run (GTK_DIALOG (dialog));
1454 case GTK_RESPONSE_OK:
1455 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1460 gtk_widget_destroy (dialog);
1462 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1464 GnomeVFSHandle *handle = NULL;
1465 GnomeVFSResult result;
1466 GtkTextIter position;
1467 GtkTextMark *insert_mark;
1469 uri = (const gchar *) uri_node->data;
1470 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1471 if (result == GNOME_VFS_OK) {
1472 GdkPixbufLoader *loader;
1474 GnomeVFSFileInfo info;
1475 gchar *filename, *basename;
1476 TnyMimePart *mime_part;
1479 const gchar *mime_type = NULL;
1481 filename = g_filename_from_uri (uri, NULL, NULL);
1482 if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
1484 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1486 mime_part = tny_platform_factory_new_mime_part
1487 (modest_runtime_get_platform_factory ());
1488 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1490 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1492 content_id = g_strdup_printf ("%d", priv->last_cid);
1493 tny_mime_part_set_content_id (mime_part, content_id);
1494 g_free (content_id);
1497 basename = g_path_get_basename (filename);
1498 tny_mime_part_set_filename (mime_part, basename);
1501 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1502 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1504 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1505 gtk_widget_show_all (priv->attachments_caption);
1506 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1509 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1510 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1511 unsigned char read_buffer[128];
1513 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1514 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
1517 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1518 g_object_ref (pixbuf);
1519 gdk_pixbuf_loader_close (loader, NULL);
1520 g_object_unref (loader);
1522 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1523 GdkPixbuf *new_pixbuf;
1525 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1526 gdk_pixbuf_get_width (pixbuf);
1527 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1528 g_object_unref (pixbuf);
1529 pixbuf = new_pixbuf;
1532 if (pixbuf != NULL) {
1533 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1534 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1535 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1544 modest_msg_edit_window_attach_file (ModestMsgEditWindow *window)
1547 ModestMsgEditWindowPrivate *priv;
1548 GtkWidget *dialog = NULL;
1550 GSList *uris = NULL;
1553 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1555 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1556 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1558 response = gtk_dialog_run (GTK_DIALOG (dialog));
1560 case GTK_RESPONSE_OK:
1561 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1566 gtk_widget_destroy (dialog);
1568 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1570 GnomeVFSHandle *handle = NULL;
1571 GnomeVFSResult result;
1573 uri = (const gchar *) uri_node->data;
1574 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1575 if (result == GNOME_VFS_OK) {
1576 TnyMimePart *mime_part;
1578 const gchar *mime_type = NULL;
1582 GnomeVFSFileInfo info;
1584 filename = g_filename_from_uri (uri, NULL, NULL);
1586 if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE) == GNOME_VFS_OK)
1587 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1588 mime_part = tny_platform_factory_new_mime_part
1589 (modest_runtime_get_platform_factory ());
1590 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1592 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1594 content_id = g_strdup_printf ("%d", priv->last_cid);
1595 tny_mime_part_set_content_id (mime_part, content_id);
1596 g_free (content_id);
1599 basename = g_path_get_basename (filename);
1600 tny_mime_part_set_filename (mime_part, basename);
1603 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1604 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1606 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1607 gtk_widget_show_all (priv->attachments_caption);
1608 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1613 g_slist_foreach (uris, (GFunc) g_free, NULL);
1614 g_slist_free (uris);
1618 modest_msg_edit_window_attach_file_noninteractive (
1619 ModestMsgEditWindow *window,
1620 const gchar *file_uri)
1623 ModestMsgEditWindowPrivate *priv;
1625 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1627 if (file_uri && strlen(file_uri)) {
1630 /* TODO: We should probably try to use only the URI,
1631 * instead of using a filename.
1633 gchar* filename = g_filename_from_uri (file_uri, NULL, NULL);
1635 g_warning("%s: g_filename_from_uri('%s') failed.\n", __FUNCTION__, file_uri);
1638 file_id = g_open (filename, O_RDONLY, 0);
1639 if (file_id != -1) {
1640 TnyMimePart *mime_part;
1642 const gchar *mime_type;
1645 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1646 mime_type = gnome_vfs_get_mime_type(filename);
1648 mime_type = gnome_vfs_get_file_mime_type_fast (filename, NULL);
1650 mime_part = tny_platform_factory_new_mime_part
1651 (modest_runtime_get_platform_factory ());
1652 stream = TNY_STREAM (tny_fs_stream_new (file_id));
1654 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1656 content_id = g_strdup_printf ("%d", priv->last_cid);
1657 tny_mime_part_set_content_id (mime_part, content_id);
1658 g_free (content_id);
1661 basename = g_path_get_basename (filename);
1662 tny_mime_part_set_filename (mime_part, basename);
1665 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1666 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1668 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1669 gtk_widget_show_all (priv->attachments_caption);
1670 } else if (file_id == -1) {
1672 g_warning("file to be attached does not exist: %s", filename);
1680 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1683 ModestMsgEditWindowPrivate *priv;
1684 gboolean clean_list = FALSE;
1686 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1687 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1689 if (att_list == NULL) {
1690 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1694 if (att_list == NULL) {
1695 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1697 GtkWidget *confirmation_dialog = NULL;
1698 gboolean dialog_response;
1700 gchar *message = NULL;
1701 const gchar *filename = NULL;
1703 if (att_list->next == NULL) {
1704 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1708 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1709 att_list->next == NULL), filename);
1710 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1712 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1713 gtk_widget_destroy (confirmation_dialog);
1714 if (!dialog_response) {
1716 g_list_free (att_list);
1719 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1721 for (node = att_list; node != NULL; node = g_list_next (node)) {
1722 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1723 const gchar *att_id;
1724 priv->attachments = g_list_remove (priv->attachments, mime_part);
1726 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1728 if (priv->attachments == NULL)
1729 gtk_widget_hide (priv->attachments_caption);
1730 att_id = tny_mime_part_get_content_id (mime_part);
1732 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1734 g_object_unref (mime_part);
1735 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1740 g_list_free (att_list);
1744 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1747 ModestMsgEditWindowPrivate *priv;
1748 GdkColor *new_color;
1749 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1751 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1752 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1755 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1757 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1759 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1761 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1766 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1769 ModestMsgEditWindowPrivate *priv;
1770 gint new_size_index;
1771 ModestMsgEditWindow *window;
1774 window = MODEST_MSG_EDIT_WINDOW (userdata);
1775 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1776 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1778 if (gtk_check_menu_item_get_active (menu_item)) {
1780 WPTextBufferFormat format;
1782 memset (&format, 0, sizeof (format));
1783 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1785 label = gtk_bin_get_child (GTK_BIN (menu_item));
1787 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1788 format.cs.font_size = TRUE;
1789 format.cs.text_position = TRUE;
1790 format.cs.font = TRUE;
1791 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1792 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1794 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1795 (gpointer) wp_get_font_size_index (new_size_index, 12)))
1796 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1798 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1799 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1800 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1806 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1809 ModestMsgEditWindowPrivate *priv;
1810 gint new_font_index;
1811 ModestMsgEditWindow *window;
1814 window = MODEST_MSG_EDIT_WINDOW (userdata);
1815 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1816 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1818 if (gtk_check_menu_item_get_active (menu_item)) {
1821 label = gtk_bin_get_child (GTK_BIN (menu_item));
1823 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1825 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1826 (gpointer) new_font_index))
1827 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1829 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1830 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1831 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1837 modest_msg_edit_window_set_zoom (ModestWindow *window,
1840 ModestMsgEditWindowPrivate *priv;
1841 ModestWindowPrivate *parent_priv;
1842 GtkRadioAction *zoom_radio_action;
1844 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1846 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1847 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1848 priv->zoom_level = zoom;
1849 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom);
1851 /* Zoom level menu options should be updated with the current zoom level */
1852 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1853 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1854 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1855 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1856 /* FIXME: Not availible before Gtk 2.10 */
1858 gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
1863 modest_msg_edit_window_get_zoom (ModestWindow *window)
1865 ModestMsgEditWindowPrivate *priv;
1867 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1869 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1870 return priv->zoom_level;
1874 zoom_allowed (ModestMsgEditWindow *window)
1878 focus = gtk_window_get_focus (GTK_WINDOW (window));
1879 return (focus != NULL && WP_IS_TEXT_VIEW (focus));
1883 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1885 ModestWindowPrivate *parent_priv;
1886 GtkRadioAction *zoom_radio_action;
1887 GSList *group, *node;
1889 /* First we check if the text view is focused. If not, zooming is not allowed */
1890 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1891 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1895 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1896 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1897 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1899 group = gtk_radio_action_get_group (zoom_radio_action);
1901 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1902 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
1906 for (node = group; node != NULL; node = g_slist_next (node)) {
1907 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1908 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1916 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1918 ModestWindowPrivate *parent_priv;
1919 GtkRadioAction *zoom_radio_action;
1920 GSList *group, *node;
1922 /* First we check if the text view is focused. If not, zooming is not allowed */
1923 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1924 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1928 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1929 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1930 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1932 group = gtk_radio_action_get_group (zoom_radio_action);
1934 for (node = group; node != NULL; node = g_slist_next (node)) {
1935 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1936 if (node->next != NULL) {
1937 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1940 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
1948 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1950 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1951 ModestWindowPrivate *parent_priv;
1952 ModestWindowMgr *mgr;
1953 gboolean is_fullscreen;
1954 GtkAction *fs_toggle_action;
1957 mgr = modest_runtime_get_window_mgr ();
1958 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1960 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1962 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1963 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1964 if (is_fullscreen != active)
1965 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1973 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
1975 ModestWindowPrivate *parent_priv;
1976 GtkAction *fs_toggle_action;
1979 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1981 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1982 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
1983 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
1987 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
1990 ModestMsgEditWindowPrivate *priv = NULL;
1991 const gchar *recipients;
1992 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1994 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1995 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1996 recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field));
1997 if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
1998 gtk_widget_show (priv->cc_caption);
2000 gtk_widget_hide (priv->cc_caption);
2001 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2005 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2008 ModestMsgEditWindowPrivate *priv = NULL;
2009 const gchar *recipients;
2010 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2012 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2013 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2014 recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field));
2015 if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2016 gtk_widget_show (priv->bcc_caption);
2018 gtk_widget_hide (priv->bcc_caption);
2019 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2023 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2024 ModestRecptEditor *editor)
2026 ModestMsgEditWindowPrivate *priv;
2028 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2029 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2030 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2032 if (editor == NULL) {
2033 GtkWidget *view_focus;
2034 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2036 /* This code should be kept in sync with ModestRecptEditor. The
2037 textview inside the recpt editor is the one that really gets the
2038 focus. As it's inside a scrolled window, and this one inside the
2039 hbox recpt editor inherits from, we'll need to go up in the
2040 hierarchy to know if the text view is part of the recpt editor
2041 or if it's a different text entry */
2043 if (gtk_widget_get_parent (view_focus)) {
2044 GtkWidget *first_parent;
2046 first_parent = gtk_widget_get_parent (view_focus);
2047 if (gtk_widget_get_parent (first_parent) &&
2048 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2049 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2054 editor = MODEST_RECPT_EDITOR (priv->to_field);
2058 modest_address_book_select_addresses (editor);
2063 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2065 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2067 modest_msg_edit_window_open_addressbook (window, NULL);
2071 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2072 gboolean show_toolbar)
2074 ModestWindowPrivate *parent_priv;
2076 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2077 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2079 /* FIXME: we can not just use the code of
2080 modest_msg_edit_window_setup_toolbar because it has a
2081 mixture of both initialization and creation code. */
2084 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2086 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2090 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2091 TnyHeaderFlags priority_flags)
2093 ModestMsgEditWindowPrivate *priv;
2094 ModestWindowPrivate *parent_priv;
2096 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2098 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2099 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2100 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2102 if (priv->priority_flags != priority_flags) {
2103 GtkAction *priority_action = NULL;
2105 priv->priority_flags = priority_flags;
2107 switch (priority_flags) {
2108 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2109 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2110 gtk_widget_show (priv->priority_icon);
2111 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2112 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2114 case TNY_HEADER_FLAG_LOW_PRIORITY:
2115 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2116 gtk_widget_show (priv->priority_icon);
2117 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2118 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2121 gtk_widget_hide (priv->priority_icon);
2122 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2123 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2126 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2127 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2132 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2135 ModestMsgEditWindowPrivate *priv;
2136 gint current_format;
2138 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2140 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2142 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2143 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2145 if (current_format != file_format) {
2146 switch (file_format) {
2147 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2148 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2150 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2154 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2155 response = gtk_dialog_run (GTK_DIALOG (dialog));
2156 gtk_widget_destroy (dialog);
2157 if (response == GTK_RESPONSE_OK)
2158 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2162 update_dimmed (window);
2167 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2170 ModestMsgEditWindowPrivate *priv;
2171 WPTextBufferFormat oldfmt, fmt;
2172 gint old_position = 0;
2176 GdkColor *color = NULL;
2177 gboolean bold, bold_set, italic, italic_set;
2178 gboolean underline, underline_set;
2179 gboolean strikethrough, strikethrough_set;
2180 gboolean position_set;
2181 gboolean font_size_set, font_set, color_set;
2184 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2185 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2187 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2189 /* First we get the currently selected font information */
2190 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2191 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2193 switch (oldfmt.text_position) {
2194 case TEXT_POSITION_NORMAL:
2197 case TEXT_POSITION_SUPERSCRIPT:
2205 g_object_set (G_OBJECT (dialog),
2206 "bold", oldfmt.bold != FALSE,
2207 "bold-set", !oldfmt.cs.bold,
2208 "underline", oldfmt.underline != FALSE,
2209 "underline-set", !oldfmt.cs.underline,
2210 "italic", oldfmt.italic != FALSE,
2211 "italic-set", !oldfmt.cs.italic,
2212 "strikethrough", oldfmt.strikethrough != FALSE,
2213 "strikethrough-set", !oldfmt.cs.strikethrough,
2214 "color", &oldfmt.color,
2215 "color-set", !oldfmt.cs.color,
2216 "size", wp_font_size[oldfmt.font_size],
2217 "size-set", !oldfmt.cs.font_size,
2218 "position", old_position,
2219 "position-set", !oldfmt.cs.text_position,
2220 "family", wp_get_font_name (oldfmt.font),
2221 "family-set", !oldfmt.cs.font,
2224 gtk_widget_show_all (dialog);
2225 response = gtk_dialog_run (GTK_DIALOG (dialog));
2226 if (response == GTK_RESPONSE_OK) {
2228 g_object_get( dialog,
2230 "bold-set", &bold_set,
2231 "underline", &underline,
2232 "underline-set", &underline_set,
2234 "italic-set", &italic_set,
2235 "strikethrough", &strikethrough,
2236 "strikethrough-set", &strikethrough_set,
2238 "color-set", &color_set,
2240 "size-set", &font_size_set,
2241 "family", &font_name,
2242 "family-set", &font_set,
2243 "position", &position,
2244 "position-set", &position_set,
2249 if (response == GTK_RESPONSE_OK) {
2250 memset(&fmt, 0, sizeof(fmt));
2256 fmt.italic = italic;
2257 fmt.cs.italic = TRUE;
2259 if (underline_set) {
2260 fmt.underline = underline;
2261 fmt.cs.underline = TRUE;
2263 if (strikethrough_set) {
2264 fmt.strikethrough = strikethrough;
2265 fmt.cs.strikethrough = TRUE;
2270 ? TEXT_POSITION_NORMAL
2271 : ( ( position == 1 )
2272 ? TEXT_POSITION_SUPERSCRIPT
2273 : TEXT_POSITION_SUBSCRIPT );
2274 fmt.cs.text_position = TRUE;
2278 fmt.cs.color = TRUE;
2281 fmt.font = wp_get_font_index(font_name,
2286 if (font_size_set) {
2287 fmt.font_size = wp_get_font_size_index(
2288 font_size, DEFAULT_FONT_SIZE);
2289 fmt.cs.font_size = TRUE;
2291 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2293 gtk_widget_destroy (dialog);
2295 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2299 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2301 ModestMsgEditWindowPrivate *priv;
2303 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2304 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2306 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2308 update_dimmed (window);
2313 update_dimmed (ModestMsgEditWindow *window)
2315 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2316 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2320 gboolean editor_focused;
2322 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2323 editor_focused = gtk_widget_is_focus (priv->msg_body);
2325 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2326 gtk_action_set_sensitive (action, rich_text && editor_focused);
2327 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2328 gtk_action_set_sensitive (action, rich_text && editor_focused);
2329 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2330 gtk_action_set_sensitive (action, rich_text && editor_focused);
2331 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2332 gtk_action_set_sensitive (action, rich_text && editor_focused);
2333 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2334 gtk_action_set_sensitive (action, rich_text && editor_focused);
2335 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2336 gtk_action_set_sensitive (action, rich_text && editor_focused);
2337 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2338 gtk_action_set_sensitive (action, rich_text && editor_focused);
2339 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2340 gtk_action_set_sensitive (action, rich_text && editor_focused);
2341 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2342 gtk_action_set_sensitive (action, rich_text && editor_focused);
2343 widget = priv->font_color_button;
2344 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2345 widget = priv->font_size_toolitem;
2346 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2347 widget = priv->font_face_toolitem;
2348 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2352 setup_insensitive_handlers (ModestMsgEditWindow *window)
2354 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2355 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2358 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2359 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2360 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2361 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2363 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2364 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2365 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2366 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2367 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2368 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2369 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2370 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2371 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2372 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2373 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2374 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2375 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2376 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2377 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2378 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2379 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2380 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2381 widget = priv->font_color_button;
2382 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2383 widget = priv->font_size_toolitem;
2384 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2385 widget = priv->font_face_toolitem;
2386 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2388 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2389 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (remove_attachment_insensitive_press), window);
2390 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2391 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (zoom_insensitive_press), window);
2393 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2394 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (paste_insensitive_press), window);
2398 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2400 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2403 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2404 gtk_action_set_sensitive (action, can_undo);
2408 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2411 GtkTextIter match_start, match_end;
2413 if (image_id == NULL)
2416 gtk_text_buffer_get_start_iter (buffer, &iter);
2418 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2419 GSList *tags = gtk_text_iter_get_tags (&match_start);
2421 for (node = tags; node != NULL; node = g_slist_next (node)) {
2422 GtkTextTag *tag = (GtkTextTag *) node->data;
2423 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2424 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2425 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2427 offset = gtk_text_iter_get_offset (&match_start);
2428 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2429 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2433 gtk_text_iter_forward_char (&iter);
2438 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2440 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2441 GtkTextIter real_start, real_end;
2442 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2444 if (gtk_text_iter_compare (start, end) > 0) {
2448 real_start = *start;
2452 GSList *tags = gtk_text_iter_get_tags (&real_start);
2454 for (node = tags; node != NULL; node = g_slist_next (node)) {
2455 GtkTextTag *tag = (GtkTextTag *) node->data;
2456 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2457 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2459 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2461 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2464 } while (gtk_text_iter_forward_char (&real_start)&&
2465 (gtk_text_iter_compare (&real_start, &real_end)<=0));
2469 msg_body_focus (GtkWidget *focus,
2470 GdkEventFocus *event,
2474 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2479 recpt_field_changed (GtkTextBuffer *buffer,
2480 ModestMsgEditWindow *editor)
2482 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2483 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2484 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2485 gboolean dim = FALSE;
2488 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2489 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2490 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2492 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2493 gtk_text_buffer_get_char_count (cc_buffer) +
2494 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2496 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2497 gtk_action_set_sensitive (action, !dim);
2498 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2499 gtk_action_set_sensitive (action, !dim);
2503 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2505 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2509 zoom_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2511 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2515 remove_attachment_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2517 ModestWindowPrivate *parent_priv;
2518 ModestMsgEditWindowPrivate *priv;
2519 GList *selected_attachments = NULL;
2520 gint n_att_selected = 0;
2522 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2523 parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2525 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2526 n_att_selected = g_list_length (selected_attachments);
2527 g_list_free (selected_attachments);
2529 if (n_att_selected > 1)
2530 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unable_to_display_more"));
2531 else if (n_att_selected == 0)
2532 hildon_banner_show_information (NULL, NULL, _("TODO: select one attachment"));
2534 hildon_banner_show_information (NULL, NULL, _("mail_ib_unable_to_purge_attachments"));
2538 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2540 gboolean rich_text, editor_focused;
2542 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2543 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2544 editor_focused = gtk_widget_is_focus (priv->msg_body);
2547 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2548 else if (!editor_focused)
2549 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2553 reset_modified (ModestMsgEditWindow *editor)
2555 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2556 GtkTextBuffer *buffer;
2558 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2559 gtk_text_buffer_set_modified (buffer, FALSE);
2560 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2561 gtk_text_buffer_set_modified (buffer, FALSE);
2562 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2563 gtk_text_buffer_set_modified (buffer, FALSE);
2564 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2568 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2570 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2571 GtkTextBuffer *buffer;
2573 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2574 if (gtk_text_buffer_get_modified (buffer))
2576 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2577 if (gtk_text_buffer_get_modified (buffer))
2579 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2580 if (gtk_text_buffer_get_modified (buffer))
2582 if (gtk_text_buffer_get_modified (priv->text_buffer))
2589 modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
2591 ModestMsgEditWindowPrivate *priv = NULL;
2593 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2594 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2596 /* check if there's no recipient added */
2597 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2598 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2599 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2600 /* no recipient contents, then select contacts */
2601 modest_msg_edit_window_open_addressbook (window, NULL);
2605 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
2607 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
2609 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
2612 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2619 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2620 ModestMsgEditWindow *window)
2622 modest_msg_edit_window_attach_file (window);
2626 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2628 ModestMsgEditWindow *window)
2630 ModestWindowPrivate *parent_priv;
2631 ModestMsgEditWindowPrivate *priv;
2635 GList *selected_attachments = NULL;
2636 gint n_att_selected = 0;
2638 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2639 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2640 selection = gtk_clipboard_wait_for_text (clipboard);
2641 focused = gtk_window_get_focus (GTK_WINDOW (window));
2643 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2644 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2645 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2646 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2648 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2649 n_att_selected = g_list_length (selected_attachments);
2650 g_list_free (selected_attachments);
2652 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2653 gtk_action_set_sensitive (action, n_att_selected == 1);
2656 update_paste_dimming (window);
2660 update_window_title (ModestMsgEditWindow *window)
2662 ModestMsgEditWindowPrivate *priv = NULL;
2663 const gchar *subject;
2665 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2666 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2667 if (subject == NULL || subject[0] == '\0')
2668 subject = _("mail_va_new_email");
2670 gtk_window_set_title (GTK_WINDOW (window), subject);
2675 subject_field_changed (GtkEditable *editable,
2676 ModestMsgEditWindow *window)
2678 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2679 update_window_title (window);
2680 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2684 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2687 ModestMsgEditWindowPrivate *priv = NULL;
2689 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2690 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2692 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2694 gtk_widget_show_all (priv->find_toolbar);
2695 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2697 gtk_widget_hide_all (priv->find_toolbar);
2698 gtk_widget_grab_focus (priv->msg_body);
2704 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2706 GtkTextIter *match_start,
2707 GtkTextIter *match_end)
2709 GtkTextIter end_iter;
2710 gchar *str_casefold;
2713 gchar *range_casefold;
2716 gboolean result = FALSE;
2723 gtk_text_iter_forward_to_end (&end_iter);
2725 str_casefold = g_utf8_casefold (str, -1);
2726 str_chars_n = strlen (str);
2728 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2729 range_casefold = g_utf8_casefold (range_text, -1);
2730 range_chars_n = strlen (range_casefold);
2732 if (range_chars_n < str_chars_n) {
2733 g_free (str_casefold);
2734 g_free (range_text);
2735 g_free (range_casefold);
2739 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2740 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2741 if (!g_utf8_collate (range_subtext, str_casefold)) {
2742 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2744 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2745 match_start, match_end, NULL);
2746 g_free (found_text);
2748 g_free (range_subtext);
2752 g_free (str_casefold);
2753 g_free (range_text);
2754 g_free (range_casefold);
2761 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2762 ModestMsgEditWindow *window)
2764 gchar *current_search = NULL;
2765 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2767 GtkTextIter selection_start, selection_end;
2768 GtkTextIter match_start, match_end;
2769 gboolean continue_search = FALSE;
2771 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2772 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2773 g_free (current_search);
2774 g_free (priv->last_search);
2775 priv->last_search = NULL;
2776 /* Information banner about empty search */
2777 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2781 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2782 continue_search = TRUE;
2784 g_free (priv->last_search);
2785 priv->last_search = g_strdup (current_search);
2788 if (continue_search) {
2789 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2790 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2791 &match_start, &match_end);
2793 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2795 GtkTextIter buffer_start;
2796 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2797 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2798 &match_start, &match_end);
2800 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2803 /* Mark as selected the string found in search */
2805 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2806 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2808 g_free (priv->last_search);
2809 priv->last_search = NULL;
2811 g_free (current_search);
2815 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2816 ModestMsgEditWindow *window)
2818 GtkToggleAction *toggle;
2819 ModestWindowPrivate *parent_priv;
2820 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2822 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2823 gtk_toggle_action_set_active (toggle, FALSE);
2828 update_paste_dimming (ModestMsgEditWindow *window)
2830 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2831 GtkAction *action = NULL;
2832 GtkClipboard *clipboard = NULL;
2836 focused = gtk_window_get_focus (GTK_WINDOW (window));
2838 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2839 active = gtk_clipboard_wait_is_text_available (clipboard);
2842 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2846 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2847 gtk_action_set_sensitive (action, active);
2852 paste_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2854 GtkWidget *focused = gtk_window_get_focus (GTK_WINDOW (editor));
2856 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2857 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_unable_to_paste_here"));
2859 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ecoc_ib_edwin_nothing_to_paste"));
2865 modest_msg_edit_window_system_clipboard_owner_change (GtkClipboard *clipboard,
2867 ModestMsgEditWindow *window)
2869 update_paste_dimming (window);
2873 update_select_all_dimming (ModestMsgEditWindow *window)
2876 gboolean dimmed = FALSE;
2878 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2880 focused = gtk_window_get_focus (GTK_WINDOW (window));
2881 if (GTK_IS_ENTRY (focused)) {
2882 const gchar *current_text;
2883 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
2884 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
2885 } else if (GTK_IS_TEXT_VIEW (focused)) {
2886 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
2887 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
2888 } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
2891 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
2892 gtk_action_set_sensitive (action, !dimmed);
2896 update_zoom_dimming (ModestMsgEditWindow *window)
2899 gboolean dimmed = FALSE;
2901 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2903 focused = gtk_window_get_focus (GTK_WINDOW (window));
2904 dimmed = ! WP_IS_TEXT_VIEW (focused);
2905 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2906 gtk_action_set_sensitive (action, !dimmed);
2910 edit_menu_activated (GtkAction *action,
2913 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2915 update_select_all_dimming (window);
2918 view_menu_activated (GtkAction *action,
2921 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2923 update_zoom_dimming (window);
2927 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
2929 ModestMsgEditWindowPrivate *priv;
2931 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
2936 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
2939 ModestMsgEditWindowPrivate *priv;
2941 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);