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 g_free (data->account_name);
1095 if (data->draft_msg != NULL) {
1096 g_object_unref (data->draft_msg);
1097 data->draft_msg = NULL;
1100 g_list_foreach (data->attachments, (GFunc)g_free, NULL);
1101 g_list_free (data->attachments);
1103 /* TODO: Free data->attachments? */
1105 g_slice_free (MsgData, data);
1109 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1112 ModestMsgEditWindowPrivate *priv = NULL;
1113 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1115 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1117 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1119 return MODEST_MSG_EDIT_FORMAT_HTML;
1121 return MODEST_MSG_EDIT_FORMAT_TEXT;
1125 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1126 ModestMsgEditFormat format)
1128 ModestMsgEditWindowPrivate *priv;
1130 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1131 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1134 case MODEST_MSG_EDIT_FORMAT_HTML:
1135 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1137 case MODEST_MSG_EDIT_FORMAT_TEXT:
1138 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1141 g_return_if_reached ();
1145 ModestMsgEditFormatState *
1146 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1148 ModestMsgEditFormatState *format_state = NULL;
1149 ModestMsgEditWindowPrivate *priv;
1150 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1152 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1153 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1155 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1157 format_state = g_new0 (ModestMsgEditFormatState, 1);
1158 format_state->bold = buffer_format->bold&0x1;
1159 format_state->italics = buffer_format->italic&0x1;
1160 format_state->bullet = buffer_format->bullet&0x1;
1161 format_state->color = buffer_format->color;
1162 format_state->font_size = buffer_format->font_size;
1163 format_state->font_family = wp_get_font_name (buffer_format->font);
1164 format_state->justification = buffer_format->justification;
1165 g_free (buffer_format);
1167 return format_state;
1172 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1173 const ModestMsgEditFormatState *format_state)
1175 ModestMsgEditWindowPrivate *priv;
1176 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1177 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1178 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1179 g_return_if_fail (format_state != NULL);
1181 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1182 gtk_widget_grab_focus (priv->msg_body);
1183 buffer_format->bold = (format_state->bold != FALSE);
1184 buffer_format->italic = (format_state->italics != FALSE);
1185 buffer_format->color = format_state->color;
1186 buffer_format->font_size = format_state->font_size;
1187 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1188 buffer_format->justification = format_state->justification;
1189 buffer_format->bullet = format_state->bullet;
1191 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1193 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1194 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1195 buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
1196 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1197 buffer_format->cs.font = (buffer_format->font != current_format->font);
1198 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1199 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1201 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1202 if (buffer_format->cs.bold) {
1203 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1205 if (buffer_format->cs.italic) {
1206 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1208 if (buffer_format->cs.color) {
1209 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1211 if (buffer_format->cs.font_size) {
1212 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1214 if (buffer_format->cs.justification) {
1215 switch (buffer_format->justification) {
1216 case GTK_JUSTIFY_LEFT:
1217 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1219 case GTK_JUSTIFY_CENTER:
1220 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1222 case GTK_JUSTIFY_RIGHT:
1223 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1230 if (buffer_format->cs.font) {
1231 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1233 if (buffer_format->cs.bullet) {
1234 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((int)buffer_format->bullet));
1236 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1237 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1239 g_free (current_format);
1244 toggle_action_set_active_block_notify (GtkToggleAction *action,
1247 GSList *proxies = NULL;
1249 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1250 proxies != NULL; proxies = g_slist_next (proxies)) {
1251 GtkWidget *widget = (GtkWidget *) proxies->data;
1252 gtk_action_block_activate_from (GTK_ACTION (action), widget);
1255 gtk_toggle_action_set_active (action, value);
1257 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1258 proxies != NULL; proxies = g_slist_next (proxies)) {
1259 GtkWidget *widget = (GtkWidget *) proxies->data;
1260 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
1265 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1267 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1269 ModestWindowPrivate *parent_priv;
1270 ModestMsgEditWindowPrivate *priv;
1271 GtkWidget *new_size_menuitem;
1272 GtkWidget *new_font_menuitem;
1274 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1275 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1277 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1278 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1279 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1280 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1282 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1283 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1284 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1287 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1289 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1290 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1292 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1293 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1295 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1296 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1298 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1299 G_CALLBACK (modest_msg_edit_window_color_button_change),
1301 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1302 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1303 G_CALLBACK (modest_msg_edit_window_color_button_change),
1306 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1307 buffer_format->font_size))->data);
1308 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1312 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1313 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1314 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1316 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1317 G_CALLBACK (modest_msg_edit_window_size_change),
1319 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1320 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1321 G_CALLBACK (modest_msg_edit_window_size_change),
1325 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1326 buffer_format->font))->data);
1327 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1331 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1332 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1333 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1335 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1336 G_CALLBACK (modest_msg_edit_window_font_change),
1338 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1339 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1340 G_CALLBACK (modest_msg_edit_window_font_change),
1344 g_free (buffer_format);
1350 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1353 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1354 ModestMsgEditWindowPrivate *priv;
1355 GtkWidget *dialog = NULL;
1357 const GdkColor *new_color = NULL;
1359 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1360 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1362 #ifdef MODEST_HILDON_VERSION_0
1363 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1364 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1366 dialog = hildon_color_chooser_new ();
1367 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1368 #endif /*MODEST_HILDON_VERSION_0*/
1369 g_free (buffer_format);
1371 response = gtk_dialog_run (GTK_DIALOG (dialog));
1373 case GTK_RESPONSE_OK: {
1374 #ifdef MODEST_HILDON_VERSION_0
1375 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1378 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1380 #endif /*MODEST_HILDON_VERSION_0*/
1387 gtk_widget_destroy (dialog);
1389 if (new_color != NULL)
1390 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1395 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1398 ModestMsgEditWindowPrivate *priv;
1399 GtkWidget *dialog = NULL;
1401 GdkColor *old_color = NULL;
1402 const GdkColor *new_color = NULL;
1404 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1405 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1407 #ifdef MODEST_HILDON_VERSION_0
1408 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1409 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1411 dialog = hildon_color_chooser_new ();
1412 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1413 #endif /*MODEST_HILDON_VERSION_9*/
1415 response = gtk_dialog_run (GTK_DIALOG (dialog));
1417 case GTK_RESPONSE_OK: {
1418 #ifdef MODEST_HILDON_VERSION_0
1419 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1422 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1424 #endif /*MODEST_HILDON_VERSION_0*/
1430 gtk_widget_destroy (dialog);
1432 if (new_color != NULL)
1433 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1439 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1442 ModestMsgEditWindowPrivate *priv;
1443 GtkWidget *dialog = NULL;
1445 GSList *uris = NULL;
1446 GSList *uri_node = NULL;
1448 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1450 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1451 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1452 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1454 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1456 response = gtk_dialog_run (GTK_DIALOG (dialog));
1458 case GTK_RESPONSE_OK:
1459 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1464 gtk_widget_destroy (dialog);
1466 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1468 GnomeVFSHandle *handle = NULL;
1469 GnomeVFSResult result;
1470 GtkTextIter position;
1471 GtkTextMark *insert_mark;
1473 uri = (const gchar *) uri_node->data;
1474 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1475 if (result == GNOME_VFS_OK) {
1476 GdkPixbufLoader *loader;
1478 GnomeVFSFileInfo info;
1479 gchar *filename, *basename;
1480 TnyMimePart *mime_part;
1483 const gchar *mime_type = NULL;
1485 filename = g_filename_from_uri (uri, NULL, NULL);
1486 if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
1488 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1490 mime_part = tny_platform_factory_new_mime_part
1491 (modest_runtime_get_platform_factory ());
1492 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1494 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1496 content_id = g_strdup_printf ("%d", priv->last_cid);
1497 tny_mime_part_set_content_id (mime_part, content_id);
1498 g_free (content_id);
1501 basename = g_path_get_basename (filename);
1502 tny_mime_part_set_filename (mime_part, basename);
1505 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1506 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1508 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1509 gtk_widget_show_all (priv->attachments_caption);
1510 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1513 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1514 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1515 unsigned char read_buffer[128];
1517 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1518 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
1521 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1522 g_object_ref (pixbuf);
1523 gdk_pixbuf_loader_close (loader, NULL);
1524 g_object_unref (loader);
1526 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1527 GdkPixbuf *new_pixbuf;
1529 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1530 gdk_pixbuf_get_width (pixbuf);
1531 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1532 g_object_unref (pixbuf);
1533 pixbuf = new_pixbuf;
1536 if (pixbuf != NULL) {
1537 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1538 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1539 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1548 modest_msg_edit_window_attach_file (ModestMsgEditWindow *window)
1551 ModestMsgEditWindowPrivate *priv;
1552 GtkWidget *dialog = NULL;
1554 GSList *uris = NULL;
1557 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1559 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1560 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1562 response = gtk_dialog_run (GTK_DIALOG (dialog));
1564 case GTK_RESPONSE_OK:
1565 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1570 gtk_widget_destroy (dialog);
1572 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1574 GnomeVFSHandle *handle = NULL;
1575 GnomeVFSResult result;
1577 uri = (const gchar *) uri_node->data;
1578 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1579 if (result == GNOME_VFS_OK) {
1580 TnyMimePart *mime_part;
1582 const gchar *mime_type = NULL;
1586 GnomeVFSFileInfo info;
1588 filename = g_filename_from_uri (uri, NULL, NULL);
1590 if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE) == GNOME_VFS_OK)
1591 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1592 mime_part = tny_platform_factory_new_mime_part
1593 (modest_runtime_get_platform_factory ());
1594 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1596 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1598 content_id = g_strdup_printf ("%d", priv->last_cid);
1599 tny_mime_part_set_content_id (mime_part, content_id);
1600 g_free (content_id);
1603 basename = g_path_get_basename (filename);
1604 tny_mime_part_set_filename (mime_part, basename);
1607 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1608 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1610 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1611 gtk_widget_show_all (priv->attachments_caption);
1612 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1617 g_slist_foreach (uris, (GFunc) g_free, NULL);
1618 g_slist_free (uris);
1622 modest_msg_edit_window_attach_file_noninteractive (
1623 ModestMsgEditWindow *window,
1624 const gchar *file_uri)
1627 ModestMsgEditWindowPrivate *priv;
1629 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1631 if (file_uri && strlen(file_uri)) {
1634 /* TODO: We should probably try to use only the URI,
1635 * instead of using a filename.
1637 gchar* filename = g_filename_from_uri (file_uri, NULL, NULL);
1639 g_warning("%s: g_filename_from_uri('%s') failed.\n", __FUNCTION__, file_uri);
1642 file_id = g_open (filename, O_RDONLY, 0);
1643 if (file_id != -1) {
1644 TnyMimePart *mime_part;
1646 const gchar *mime_type;
1649 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1650 mime_type = gnome_vfs_get_mime_type(filename);
1652 mime_type = gnome_vfs_get_file_mime_type_fast (filename, NULL);
1654 mime_part = tny_platform_factory_new_mime_part
1655 (modest_runtime_get_platform_factory ());
1656 stream = TNY_STREAM (tny_fs_stream_new (file_id));
1658 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1660 content_id = g_strdup_printf ("%d", priv->last_cid);
1661 tny_mime_part_set_content_id (mime_part, content_id);
1662 g_free (content_id);
1665 basename = g_path_get_basename (filename);
1666 tny_mime_part_set_filename (mime_part, basename);
1669 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1670 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1672 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1673 gtk_widget_show_all (priv->attachments_caption);
1674 } else if (file_id == -1) {
1676 g_warning("file to be attached does not exist: %s", filename);
1684 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1687 ModestMsgEditWindowPrivate *priv;
1688 gboolean clean_list = FALSE;
1690 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1691 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1693 if (att_list == NULL) {
1694 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1698 if (att_list == NULL) {
1699 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1701 GtkWidget *confirmation_dialog = NULL;
1702 gboolean dialog_response;
1704 gchar *message = NULL;
1705 const gchar *filename = NULL;
1707 if (att_list->next == NULL) {
1708 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1712 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1713 att_list->next == NULL), filename);
1714 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1716 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1717 gtk_widget_destroy (confirmation_dialog);
1718 if (!dialog_response) {
1720 g_list_free (att_list);
1723 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1725 for (node = att_list; node != NULL; node = g_list_next (node)) {
1726 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1727 const gchar *att_id;
1728 priv->attachments = g_list_remove (priv->attachments, mime_part);
1730 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1732 if (priv->attachments == NULL)
1733 gtk_widget_hide (priv->attachments_caption);
1734 att_id = tny_mime_part_get_content_id (mime_part);
1736 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1738 g_object_unref (mime_part);
1739 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1744 g_list_free (att_list);
1748 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1751 ModestMsgEditWindowPrivate *priv;
1752 GdkColor *new_color;
1753 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1755 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1756 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1759 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1761 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1763 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1765 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1770 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1773 ModestMsgEditWindowPrivate *priv;
1774 gint new_size_index;
1775 ModestMsgEditWindow *window;
1778 window = MODEST_MSG_EDIT_WINDOW (userdata);
1779 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1780 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1782 if (gtk_check_menu_item_get_active (menu_item)) {
1784 WPTextBufferFormat format;
1786 memset (&format, 0, sizeof (format));
1787 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1789 label = gtk_bin_get_child (GTK_BIN (menu_item));
1791 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1792 format.cs.font_size = TRUE;
1793 format.cs.text_position = TRUE;
1794 format.cs.font = TRUE;
1795 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1796 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1798 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1799 (gpointer) wp_get_font_size_index (new_size_index, 12)))
1800 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1802 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1803 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1804 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1810 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1813 ModestMsgEditWindowPrivate *priv;
1814 gint new_font_index;
1815 ModestMsgEditWindow *window;
1818 window = MODEST_MSG_EDIT_WINDOW (userdata);
1819 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1820 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1822 if (gtk_check_menu_item_get_active (menu_item)) {
1825 label = gtk_bin_get_child (GTK_BIN (menu_item));
1827 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1829 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1830 (gpointer) new_font_index))
1831 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1833 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1834 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1835 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1841 modest_msg_edit_window_set_zoom (ModestWindow *window,
1844 ModestMsgEditWindowPrivate *priv;
1845 ModestWindowPrivate *parent_priv;
1846 GtkRadioAction *zoom_radio_action;
1848 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1850 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1851 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1852 priv->zoom_level = zoom;
1853 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom);
1855 /* Zoom level menu options should be updated with the current zoom level */
1856 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1857 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1858 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1859 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1860 /* FIXME: Not availible before Gtk 2.10 */
1862 gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
1867 modest_msg_edit_window_get_zoom (ModestWindow *window)
1869 ModestMsgEditWindowPrivate *priv;
1871 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1873 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1874 return priv->zoom_level;
1878 zoom_allowed (ModestMsgEditWindow *window)
1882 focus = gtk_window_get_focus (GTK_WINDOW (window));
1883 return (focus != NULL && WP_IS_TEXT_VIEW (focus));
1887 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1889 ModestWindowPrivate *parent_priv;
1890 GtkRadioAction *zoom_radio_action;
1891 GSList *group, *node;
1893 /* First we check if the text view is focused. If not, zooming is not allowed */
1894 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1895 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1899 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1900 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1901 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1903 group = gtk_radio_action_get_group (zoom_radio_action);
1905 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1906 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
1910 for (node = group; node != NULL; node = g_slist_next (node)) {
1911 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1912 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1920 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1922 ModestWindowPrivate *parent_priv;
1923 GtkRadioAction *zoom_radio_action;
1924 GSList *group, *node;
1926 /* First we check if the text view is focused. If not, zooming is not allowed */
1927 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1928 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1932 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1933 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1934 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1936 group = gtk_radio_action_get_group (zoom_radio_action);
1938 for (node = group; node != NULL; node = g_slist_next (node)) {
1939 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1940 if (node->next != NULL) {
1941 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1944 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
1952 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1954 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1955 ModestWindowPrivate *parent_priv;
1956 ModestWindowMgr *mgr;
1957 gboolean is_fullscreen;
1958 GtkAction *fs_toggle_action;
1961 mgr = modest_runtime_get_window_mgr ();
1962 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1964 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1966 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1967 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1968 if (is_fullscreen != active)
1969 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1977 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
1979 ModestWindowPrivate *parent_priv;
1980 GtkAction *fs_toggle_action;
1983 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1985 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1986 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
1987 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
1991 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
1994 ModestMsgEditWindowPrivate *priv = NULL;
1995 const gchar *recipients;
1996 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1998 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1999 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2000 recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field));
2001 if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2002 gtk_widget_show (priv->cc_caption);
2004 gtk_widget_hide (priv->cc_caption);
2005 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2009 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2012 ModestMsgEditWindowPrivate *priv = NULL;
2013 const gchar *recipients;
2014 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2016 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2017 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2018 recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field));
2019 if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2020 gtk_widget_show (priv->bcc_caption);
2022 gtk_widget_hide (priv->bcc_caption);
2023 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2027 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2028 ModestRecptEditor *editor)
2030 ModestMsgEditWindowPrivate *priv;
2032 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2033 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2034 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2036 if (editor == NULL) {
2037 GtkWidget *view_focus;
2038 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2040 /* This code should be kept in sync with ModestRecptEditor. The
2041 textview inside the recpt editor is the one that really gets the
2042 focus. As it's inside a scrolled window, and this one inside the
2043 hbox recpt editor inherits from, we'll need to go up in the
2044 hierarchy to know if the text view is part of the recpt editor
2045 or if it's a different text entry */
2047 if (gtk_widget_get_parent (view_focus)) {
2048 GtkWidget *first_parent;
2050 first_parent = gtk_widget_get_parent (view_focus);
2051 if (gtk_widget_get_parent (first_parent) &&
2052 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2053 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2058 editor = MODEST_RECPT_EDITOR (priv->to_field);
2062 modest_address_book_select_addresses (editor);
2067 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2069 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2071 modest_msg_edit_window_open_addressbook (window, NULL);
2075 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2076 gboolean show_toolbar)
2078 ModestWindowPrivate *parent_priv;
2080 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2081 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2083 /* FIXME: we can not just use the code of
2084 modest_msg_edit_window_setup_toolbar because it has a
2085 mixture of both initialization and creation code. */
2088 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2090 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2094 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2095 TnyHeaderFlags priority_flags)
2097 ModestMsgEditWindowPrivate *priv;
2098 ModestWindowPrivate *parent_priv;
2100 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2102 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2103 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2104 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2106 if (priv->priority_flags != priority_flags) {
2107 GtkAction *priority_action = NULL;
2109 priv->priority_flags = priority_flags;
2111 switch (priority_flags) {
2112 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2113 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2114 gtk_widget_show (priv->priority_icon);
2115 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2116 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2118 case TNY_HEADER_FLAG_LOW_PRIORITY:
2119 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2120 gtk_widget_show (priv->priority_icon);
2121 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2122 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2125 gtk_widget_hide (priv->priority_icon);
2126 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2127 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2130 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2131 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2136 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2139 ModestMsgEditWindowPrivate *priv;
2140 gint current_format;
2142 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2144 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2146 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2147 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2149 if (current_format != file_format) {
2150 switch (file_format) {
2151 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2152 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2154 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2158 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2159 response = gtk_dialog_run (GTK_DIALOG (dialog));
2160 gtk_widget_destroy (dialog);
2161 if (response == GTK_RESPONSE_OK)
2162 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2166 update_dimmed (window);
2171 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2174 ModestMsgEditWindowPrivate *priv;
2175 WPTextBufferFormat oldfmt, fmt;
2176 gint old_position = 0;
2180 GdkColor *color = NULL;
2181 gboolean bold, bold_set, italic, italic_set;
2182 gboolean underline, underline_set;
2183 gboolean strikethrough, strikethrough_set;
2184 gboolean position_set;
2185 gboolean font_size_set, font_set, color_set;
2188 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2189 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2191 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2193 /* First we get the currently selected font information */
2194 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2195 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2197 switch (oldfmt.text_position) {
2198 case TEXT_POSITION_NORMAL:
2201 case TEXT_POSITION_SUPERSCRIPT:
2209 g_object_set (G_OBJECT (dialog),
2210 "bold", oldfmt.bold != FALSE,
2211 "bold-set", !oldfmt.cs.bold,
2212 "underline", oldfmt.underline != FALSE,
2213 "underline-set", !oldfmt.cs.underline,
2214 "italic", oldfmt.italic != FALSE,
2215 "italic-set", !oldfmt.cs.italic,
2216 "strikethrough", oldfmt.strikethrough != FALSE,
2217 "strikethrough-set", !oldfmt.cs.strikethrough,
2218 "color", &oldfmt.color,
2219 "color-set", !oldfmt.cs.color,
2220 "size", wp_font_size[oldfmt.font_size],
2221 "size-set", !oldfmt.cs.font_size,
2222 "position", old_position,
2223 "position-set", !oldfmt.cs.text_position,
2224 "family", wp_get_font_name (oldfmt.font),
2225 "family-set", !oldfmt.cs.font,
2228 gtk_widget_show_all (dialog);
2229 response = gtk_dialog_run (GTK_DIALOG (dialog));
2230 if (response == GTK_RESPONSE_OK) {
2232 g_object_get( dialog,
2234 "bold-set", &bold_set,
2235 "underline", &underline,
2236 "underline-set", &underline_set,
2238 "italic-set", &italic_set,
2239 "strikethrough", &strikethrough,
2240 "strikethrough-set", &strikethrough_set,
2242 "color-set", &color_set,
2244 "size-set", &font_size_set,
2245 "family", &font_name,
2246 "family-set", &font_set,
2247 "position", &position,
2248 "position-set", &position_set,
2253 if (response == GTK_RESPONSE_OK) {
2254 memset(&fmt, 0, sizeof(fmt));
2260 fmt.italic = italic;
2261 fmt.cs.italic = TRUE;
2263 if (underline_set) {
2264 fmt.underline = underline;
2265 fmt.cs.underline = TRUE;
2267 if (strikethrough_set) {
2268 fmt.strikethrough = strikethrough;
2269 fmt.cs.strikethrough = TRUE;
2274 ? TEXT_POSITION_NORMAL
2275 : ( ( position == 1 )
2276 ? TEXT_POSITION_SUPERSCRIPT
2277 : TEXT_POSITION_SUBSCRIPT );
2278 fmt.cs.text_position = TRUE;
2282 fmt.cs.color = TRUE;
2285 fmt.font = wp_get_font_index(font_name,
2290 if (font_size_set) {
2291 fmt.font_size = wp_get_font_size_index(
2292 font_size, DEFAULT_FONT_SIZE);
2293 fmt.cs.font_size = TRUE;
2295 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2297 gtk_widget_destroy (dialog);
2299 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2303 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2305 ModestMsgEditWindowPrivate *priv;
2307 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2308 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2310 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2312 update_dimmed (window);
2317 update_dimmed (ModestMsgEditWindow *window)
2319 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2320 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2324 gboolean editor_focused;
2326 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2327 editor_focused = gtk_widget_is_focus (priv->msg_body);
2329 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2330 gtk_action_set_sensitive (action, rich_text && editor_focused);
2331 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2332 gtk_action_set_sensitive (action, rich_text && editor_focused);
2333 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2334 gtk_action_set_sensitive (action, rich_text && editor_focused);
2335 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2336 gtk_action_set_sensitive (action, rich_text && editor_focused);
2337 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2338 gtk_action_set_sensitive (action, rich_text && editor_focused);
2339 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2340 gtk_action_set_sensitive (action, rich_text && editor_focused);
2341 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2342 gtk_action_set_sensitive (action, rich_text && editor_focused);
2343 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2344 gtk_action_set_sensitive (action, rich_text && editor_focused);
2345 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2346 gtk_action_set_sensitive (action, rich_text && editor_focused);
2347 widget = priv->font_color_button;
2348 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2349 widget = priv->font_size_toolitem;
2350 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2351 widget = priv->font_face_toolitem;
2352 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2356 setup_insensitive_handlers (ModestMsgEditWindow *window)
2358 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2359 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2362 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2363 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2364 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2365 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2367 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
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/BulletedListMenu");
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");
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/AlignmentLeftMenu");
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/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
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, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
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, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2380 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2381 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2382 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2383 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2384 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2385 widget = priv->font_color_button;
2386 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2387 widget = priv->font_size_toolitem;
2388 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2389 widget = priv->font_face_toolitem;
2390 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2392 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2393 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (remove_attachment_insensitive_press), window);
2394 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2395 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (zoom_insensitive_press), window);
2397 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2398 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (paste_insensitive_press), window);
2402 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2404 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2407 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2408 gtk_action_set_sensitive (action, can_undo);
2412 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2415 GtkTextIter match_start, match_end;
2417 if (image_id == NULL)
2420 gtk_text_buffer_get_start_iter (buffer, &iter);
2422 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2423 GSList *tags = gtk_text_iter_get_tags (&match_start);
2425 for (node = tags; node != NULL; node = g_slist_next (node)) {
2426 GtkTextTag *tag = (GtkTextTag *) node->data;
2427 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2428 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2429 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2431 offset = gtk_text_iter_get_offset (&match_start);
2432 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2433 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2437 gtk_text_iter_forward_char (&iter);
2442 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2444 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2445 GtkTextIter real_start, real_end;
2446 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2448 if (gtk_text_iter_compare (start, end) > 0) {
2452 real_start = *start;
2456 GSList *tags = gtk_text_iter_get_tags (&real_start);
2458 for (node = tags; node != NULL; node = g_slist_next (node)) {
2459 GtkTextTag *tag = (GtkTextTag *) node->data;
2460 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2461 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2463 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2465 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2468 } while (gtk_text_iter_forward_char (&real_start)&&
2469 (gtk_text_iter_compare (&real_start, &real_end)<=0));
2473 msg_body_focus (GtkWidget *focus,
2474 GdkEventFocus *event,
2478 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2483 recpt_field_changed (GtkTextBuffer *buffer,
2484 ModestMsgEditWindow *editor)
2486 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2487 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2488 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2489 gboolean dim = FALSE;
2492 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2493 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2494 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2496 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2497 gtk_text_buffer_get_char_count (cc_buffer) +
2498 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2500 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2501 gtk_action_set_sensitive (action, !dim);
2502 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2503 gtk_action_set_sensitive (action, !dim);
2507 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2509 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2513 zoom_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2515 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2519 remove_attachment_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2521 ModestWindowPrivate *parent_priv;
2522 ModestMsgEditWindowPrivate *priv;
2523 GList *selected_attachments = NULL;
2524 gint n_att_selected = 0;
2526 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2527 parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2529 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2530 n_att_selected = g_list_length (selected_attachments);
2531 g_list_free (selected_attachments);
2533 if (n_att_selected > 1)
2534 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unable_to_display_more"));
2535 else if (n_att_selected == 0)
2536 hildon_banner_show_information (NULL, NULL, _("TODO: select one attachment"));
2538 hildon_banner_show_information (NULL, NULL, _("mail_ib_unable_to_purge_attachments"));
2542 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2544 gboolean rich_text, editor_focused;
2546 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2547 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2548 editor_focused = gtk_widget_is_focus (priv->msg_body);
2551 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2552 else if (!editor_focused)
2553 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2557 reset_modified (ModestMsgEditWindow *editor)
2559 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2560 GtkTextBuffer *buffer;
2562 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2563 gtk_text_buffer_set_modified (buffer, FALSE);
2564 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2565 gtk_text_buffer_set_modified (buffer, FALSE);
2566 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2567 gtk_text_buffer_set_modified (buffer, FALSE);
2568 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2572 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2574 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2575 GtkTextBuffer *buffer;
2577 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2578 if (gtk_text_buffer_get_modified (buffer))
2580 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2581 if (gtk_text_buffer_get_modified (buffer))
2583 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2584 if (gtk_text_buffer_get_modified (buffer))
2586 if (gtk_text_buffer_get_modified (priv->text_buffer))
2593 modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
2595 ModestMsgEditWindowPrivate *priv = NULL;
2597 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2598 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2600 /* check if there's no recipient added */
2601 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2602 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2603 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2604 /* no recipient contents, then select contacts */
2605 modest_msg_edit_window_open_addressbook (window, NULL);
2609 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
2611 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
2613 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
2616 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2623 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2624 ModestMsgEditWindow *window)
2626 modest_msg_edit_window_attach_file (window);
2630 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2632 ModestMsgEditWindow *window)
2634 ModestWindowPrivate *parent_priv;
2635 ModestMsgEditWindowPrivate *priv;
2639 GList *selected_attachments = NULL;
2640 gint n_att_selected = 0;
2642 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2643 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2644 selection = gtk_clipboard_wait_for_text (clipboard);
2645 focused = gtk_window_get_focus (GTK_WINDOW (window));
2647 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2648 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2649 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2650 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2652 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2653 n_att_selected = g_list_length (selected_attachments);
2654 g_list_free (selected_attachments);
2656 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2657 gtk_action_set_sensitive (action, n_att_selected == 1);
2660 update_paste_dimming (window);
2664 update_window_title (ModestMsgEditWindow *window)
2666 ModestMsgEditWindowPrivate *priv = NULL;
2667 const gchar *subject;
2669 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2670 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2671 if (subject == NULL || subject[0] == '\0')
2672 subject = _("mail_va_new_email");
2674 gtk_window_set_title (GTK_WINDOW (window), subject);
2679 subject_field_changed (GtkEditable *editable,
2680 ModestMsgEditWindow *window)
2682 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2683 update_window_title (window);
2684 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2688 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2691 ModestMsgEditWindowPrivate *priv = NULL;
2693 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2694 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2696 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2698 gtk_widget_show_all (priv->find_toolbar);
2699 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2701 gtk_widget_hide_all (priv->find_toolbar);
2702 gtk_widget_grab_focus (priv->msg_body);
2708 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2710 GtkTextIter *match_start,
2711 GtkTextIter *match_end)
2713 GtkTextIter end_iter;
2714 gchar *str_casefold;
2717 gchar *range_casefold;
2720 gboolean result = FALSE;
2727 gtk_text_iter_forward_to_end (&end_iter);
2729 str_casefold = g_utf8_casefold (str, -1);
2730 str_chars_n = strlen (str);
2732 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2733 range_casefold = g_utf8_casefold (range_text, -1);
2734 range_chars_n = strlen (range_casefold);
2736 if (range_chars_n < str_chars_n) {
2737 g_free (str_casefold);
2738 g_free (range_text);
2739 g_free (range_casefold);
2743 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2744 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2745 if (!g_utf8_collate (range_subtext, str_casefold)) {
2746 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2748 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2749 match_start, match_end, NULL);
2750 g_free (found_text);
2752 g_free (range_subtext);
2756 g_free (str_casefold);
2757 g_free (range_text);
2758 g_free (range_casefold);
2765 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2766 ModestMsgEditWindow *window)
2768 gchar *current_search = NULL;
2769 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2771 GtkTextIter selection_start, selection_end;
2772 GtkTextIter match_start, match_end;
2773 gboolean continue_search = FALSE;
2775 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2776 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2777 g_free (current_search);
2778 g_free (priv->last_search);
2779 priv->last_search = NULL;
2780 /* Information banner about empty search */
2781 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2785 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2786 continue_search = TRUE;
2788 g_free (priv->last_search);
2789 priv->last_search = g_strdup (current_search);
2792 if (continue_search) {
2793 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2794 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2795 &match_start, &match_end);
2797 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2799 GtkTextIter buffer_start;
2800 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2801 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2802 &match_start, &match_end);
2804 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2807 /* Mark as selected the string found in search */
2809 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2810 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2812 g_free (priv->last_search);
2813 priv->last_search = NULL;
2815 g_free (current_search);
2819 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2820 ModestMsgEditWindow *window)
2822 GtkToggleAction *toggle;
2823 ModestWindowPrivate *parent_priv;
2824 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2826 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2827 gtk_toggle_action_set_active (toggle, FALSE);
2832 update_paste_dimming (ModestMsgEditWindow *window)
2834 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2835 GtkAction *action = NULL;
2836 GtkClipboard *clipboard = NULL;
2840 focused = gtk_window_get_focus (GTK_WINDOW (window));
2842 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2843 active = gtk_clipboard_wait_is_text_available (clipboard);
2846 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2850 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2851 gtk_action_set_sensitive (action, active);
2856 paste_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2858 GtkWidget *focused = gtk_window_get_focus (GTK_WINDOW (editor));
2860 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2861 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_unable_to_paste_here"));
2863 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ecoc_ib_edwin_nothing_to_paste"));
2869 modest_msg_edit_window_system_clipboard_owner_change (GtkClipboard *clipboard,
2871 ModestMsgEditWindow *window)
2873 update_paste_dimming (window);
2877 update_select_all_dimming (ModestMsgEditWindow *window)
2880 gboolean dimmed = FALSE;
2882 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2884 focused = gtk_window_get_focus (GTK_WINDOW (window));
2885 if (GTK_IS_ENTRY (focused)) {
2886 const gchar *current_text;
2887 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
2888 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
2889 } else if (GTK_IS_TEXT_VIEW (focused)) {
2890 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
2891 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
2892 } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
2895 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
2896 gtk_action_set_sensitive (action, !dimmed);
2900 update_zoom_dimming (ModestMsgEditWindow *window)
2903 gboolean dimmed = FALSE;
2905 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2907 focused = gtk_window_get_focus (GTK_WINDOW (window));
2908 dimmed = ! WP_IS_TEXT_VIEW (focused);
2909 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2910 gtk_action_set_sensitive (action, !dimmed);
2914 edit_menu_activated (GtkAction *action,
2917 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2919 update_select_all_dimming (window);
2922 view_menu_activated (GtkAction *action,
2925 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2927 update_zoom_dimming (window);
2931 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
2933 ModestMsgEditWindowPrivate *priv;
2935 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
2940 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
2943 ModestMsgEditWindowPrivate *priv;
2945 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);