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 copy_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
98 static void setup_insensitive_handlers (ModestMsgEditWindow *editor);
99 static void reset_modified (ModestMsgEditWindow *editor);
101 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
102 static void text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata);
103 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
104 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
105 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
106 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
108 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
110 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
112 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
113 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
114 GdkEventWindowState *event,
116 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
117 ModestRecptEditor *editor);
118 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
119 ModestMsgEditWindow *window);
121 /* ModestWindow methods implementation */
122 static void modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom);
123 static gdouble modest_msg_edit_window_get_zoom (ModestWindow *window);
124 static gboolean modest_msg_edit_window_zoom_minus (ModestWindow *window);
125 static gboolean modest_msg_edit_window_zoom_plus (ModestWindow *window);
126 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
127 gboolean show_toolbar);
128 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
130 ModestMsgEditWindow *window);
131 static void modest_msg_edit_window_system_clipboard_owner_change (GtkClipboard *clipboard,
133 ModestMsgEditWindow *window);
134 static void update_window_title (ModestMsgEditWindow *window);
135 static void update_dimmed (ModestMsgEditWindow *window);
136 static void update_paste_dimming (ModestMsgEditWindow *window);
137 static void update_select_all_dimming (ModestMsgEditWindow *window);
138 static void update_zoom_dimming (ModestMsgEditWindow *window);
141 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
142 ModestMsgEditWindow *window);
143 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
144 ModestMsgEditWindow *window);
145 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
147 GtkTextIter *match_start,
148 GtkTextIter *match_end);
152 /* static gboolean */
153 /* on_key_pressed (GtkWidget *self, */
154 /* GdkEventKey *event, */
155 /* gpointer user_data); */
157 static void edit_menu_activated (GtkAction *action,
159 static void view_menu_activated (GtkAction *action,
162 /* list my signals */
169 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
170 struct _ModestMsgEditWindowPrivate {
172 GtkWidget *header_box;
174 ModestPairList *from_field_protos;
175 GtkWidget *from_field;
179 GtkWidget *bcc_field;
180 GtkWidget *subject_field;
181 GtkWidget *attachments_view;
182 GtkWidget *priority_icon;
183 GtkWidget *add_attachment_button;
185 GtkWidget *cc_caption;
186 GtkWidget *bcc_caption;
187 GtkWidget *attachments_caption;
189 GtkTextBuffer *text_buffer;
191 GtkWidget *font_size_toolitem;
192 GtkWidget *font_face_toolitem;
193 GtkWidget *font_color_button;
194 GSList *font_items_group;
195 GtkWidget *font_tool_button_label;
196 GSList *size_items_group;
197 GtkWidget *size_tool_button_label;
199 GtkWidget *find_toolbar;
203 GtkWidget *scroll_area;
208 TnyHeaderFlags priority_flags;
212 gulong clipboard_change_handler_id;
213 gulong system_clipboard_change_handler_id;
219 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
220 MODEST_TYPE_MSG_EDIT_WINDOW, \
221 ModestMsgEditWindowPrivate))
223 static GtkWindowClass *parent_class = NULL;
225 /* uncomment the following if you have defined any signals */
226 /* static guint signals[LAST_SIGNAL] = {0}; */
229 modest_msg_edit_window_get_type (void)
231 static GType my_type = 0;
233 static const GTypeInfo my_info = {
234 sizeof(ModestMsgEditWindowClass),
235 NULL, /* base init */
236 NULL, /* base finalize */
237 (GClassInitFunc) modest_msg_edit_window_class_init,
238 NULL, /* class finalize */
239 NULL, /* class data */
240 sizeof(ModestMsgEditWindow),
242 (GInstanceInitFunc) modest_msg_edit_window_init,
245 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
246 "ModestMsgEditWindow",
249 wp_text_buffer_library_init ();
255 save_state (ModestWindow *self)
257 modest_widget_memory_save (modest_runtime_get_conf(),
258 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
263 restore_settings (ModestMsgEditWindow *self)
265 modest_widget_memory_restore (modest_runtime_get_conf(),
266 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
271 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
273 GObjectClass *gobject_class;
274 ModestWindowClass *modest_window_class;
275 gobject_class = (GObjectClass*) klass;
276 modest_window_class = (ModestWindowClass*) klass;
278 parent_class = g_type_class_peek_parent (klass);
279 gobject_class->finalize = modest_msg_edit_window_finalize;
281 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
282 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
283 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
284 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
285 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
286 modest_window_class->save_state_func = save_state;
288 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
294 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
296 ModestMsgEditWindowPrivate *priv;
297 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
299 priv->msg_body = NULL;
300 priv->from_field = NULL;
301 priv->to_field = NULL;
302 priv->cc_field = NULL;
303 priv->bcc_field = NULL;
304 priv->subject_field = NULL;
305 priv->attachments = NULL;
307 priv->zoom_level = 1.0;
309 priv->cc_caption = NULL;
310 priv->bcc_caption = NULL;
312 priv->priority_flags = 0;
314 priv->find_toolbar = NULL;
315 priv->last_search = NULL;
317 priv->draft_msg = NULL;
318 priv->clipboard_change_handler_id = 0;
319 priv->system_clipboard_change_handler_id = 0;
324 /* FIXME: this is a dup from the one in gtk/ */
327 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
329 static ModestPairList*
330 get_transports (void)
332 GSList *transports = NULL;
334 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
335 GSList *accounts = modest_account_mgr_account_names (account_mgr,
336 TRUE /* only enabled accounts. */);
338 GSList *cursor = accounts;
340 gchar *account_name = cursor->data;
341 gchar *from_string = NULL;
343 from_string = modest_account_mgr_get_from_string (account_mgr,
347 if (from_string && account_name) {
348 gchar *name = account_name;
349 ModestPair *pair = modest_pair_new ((gpointer) name,
350 (gpointer) from_string , TRUE);
351 transports = g_slist_prepend (transports, pair);
354 cursor = cursor->next;
356 g_slist_free (accounts); /* only free the accounts, not the elements,
357 * because they are used in the pairlist */
363 init_window (ModestMsgEditWindow *obj)
365 GtkWidget *from_caption, *to_caption, *subject_caption;
366 GtkWidget *main_vbox;
367 ModestMsgEditWindowPrivate *priv;
369 GtkSizeGroup *size_group;
371 GtkWidget *subject_box;
372 GtkWidget *attachment_icon;
373 GtkWidget *window_box;
375 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
377 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
379 /* Note: This ModestPairList* must exist for as long as the combo
380 * that uses it, because the ModestComboBox uses the ID opaquely,
381 * so it can't know how to manage its memory. */
382 priv->from_field_protos = get_transports ();
384 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
386 priv->to_field = modest_recpt_editor_new ();
387 priv->cc_field = modest_recpt_editor_new ();
388 priv->bcc_field = modest_recpt_editor_new ();
389 subject_box = gtk_hbox_new (FALSE, 0);
390 priv->priority_icon = gtk_image_new ();
391 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
392 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
393 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
394 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
395 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
396 priv->add_attachment_button = gtk_button_new ();
397 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
398 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
399 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
400 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
401 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
402 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
403 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
404 priv->attachments_view = modest_attachments_view_new (NULL);
406 priv->header_box = gtk_vbox_new (FALSE, 0);
408 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
409 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
410 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
411 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
412 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
413 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
414 g_object_unref (size_group);
416 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
417 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
418 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
419 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
420 gtk_size_group_add_widget (size_group, priv->subject_field);
421 gtk_size_group_add_widget (size_group, priv->attachments_view);
422 g_object_unref (size_group);
424 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
425 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
426 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
427 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
428 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
429 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
430 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
433 priv->msg_body = wp_text_view_new ();
434 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
435 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
436 g_object_set (priv->text_buffer, "font_scale", 1.0, NULL);
437 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
438 /* gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
439 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
441 priv->find_toolbar = hildon_find_toolbar_new (NULL);
442 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
444 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
446 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
447 G_CALLBACK (text_buffer_refresh_attributes), obj);
448 g_signal_connect (G_OBJECT (priv->text_buffer), "delete-range",
449 G_CALLBACK (text_buffer_delete_range), obj);
450 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
451 G_CALLBACK (text_buffer_can_undo), obj);
452 g_signal_connect (G_OBJECT (obj), "window-state-event",
453 G_CALLBACK (modest_msg_edit_window_window_state_event),
455 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
456 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
457 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
458 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
459 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
460 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
462 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
463 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
465 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
466 G_CALLBACK (msg_body_focus), obj);
467 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
468 G_CALLBACK (msg_body_focus), obj);
469 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
470 "changed", G_CALLBACK (recpt_field_changed), obj);
471 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
472 "changed", G_CALLBACK (recpt_field_changed), obj);
473 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
474 "changed", G_CALLBACK (recpt_field_changed), obj);
475 recpt_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
476 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
478 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
479 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
481 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
482 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
483 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
485 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
487 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
488 frame = gtk_frame_new (NULL);
489 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
491 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
492 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
493 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
495 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL)) {
496 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
497 gtk_widget_hide (priv->cc_caption);
499 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL)) {
500 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
501 gtk_widget_hide (priv->bcc_caption);
504 window_box = gtk_vbox_new (FALSE, 0);
505 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
506 gtk_box_pack_end (GTK_BOX (window_box), priv->find_toolbar, FALSE, FALSE, 0);
507 gtk_container_add (GTK_CONTAINER(obj), window_box);
508 priv->scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
509 gtk_container_add (GTK_CONTAINER (frame), priv->scroll_area);
512 TODO: scroll_area was never instantiated.
513 Stop building without warnings-as-errors. murrayc.
514 gtk_container_set_focus_vadjustment (GTK_CONTAINER (scroll_area),
515 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
518 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
519 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
520 priv->system_clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
521 G_CALLBACK (modest_msg_edit_window_system_clipboard_owner_change), obj);
527 modest_msg_edit_window_finalize (GObject *obj)
529 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
531 if (priv->clipboard_change_handler_id > 0) {
532 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), priv->clipboard_change_handler_id);
533 priv->clipboard_change_handler_id = 0;
536 if (priv->system_clipboard_change_handler_id > 0) {
537 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
538 priv->system_clipboard_change_handler_id);
539 priv->system_clipboard_change_handler_id = 0;
542 if (priv->draft_msg != NULL) {
543 g_object_unref (priv->draft_msg);
544 priv->draft_msg = NULL;
547 /* This had to stay alive for as long as the combobox that used it: */
548 modest_pair_list_free (priv->from_field_protos);
550 G_OBJECT_CLASS(parent_class)->finalize (obj);
554 menubar_to_menu (GtkUIManager *ui_manager)
556 GtkWidget *main_menu;
560 /* Create new main menu */
561 main_menu = gtk_menu_new();
563 /* Get the menubar from the UI manager */
564 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
566 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
570 menu = GTK_WIDGET (iter->data);
571 gtk_widget_reparent(menu, main_menu);
573 iter = g_list_next (iter);
580 set_msg (ModestMsgEditWindow *self, TnyMsg *msg)
583 const gchar *to, *cc, *bcc, *subject;
585 ModestMsgEditWindowPrivate *priv;
587 TnyHeaderFlags priority_flags;
589 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
590 g_return_if_fail (TNY_IS_MSG (msg));
592 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
594 header = tny_msg_get_header (msg);
595 to = tny_header_get_to (header);
596 cc = tny_header_get_cc (header);
597 bcc = tny_header_get_bcc (header);
598 subject = tny_header_get_subject (header);
599 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
602 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
604 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
605 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
606 gtk_widget_show (priv->cc_caption);
607 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
608 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
609 gtk_widget_hide (priv->cc_caption);
612 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
613 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
614 gtk_widget_show (priv->bcc_caption);
615 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
616 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
617 gtk_widget_hide (priv->bcc_caption);
620 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
621 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
624 update_window_title (self);
626 /* gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
627 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
628 body = modest_tny_msg_get_body (msg, TRUE);
630 if ((body == NULL)||(body[0] == '\0')) {
632 body = modest_text_utils_convert_to_html ("");
634 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
635 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
638 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
641 /* Get the default format required from configuration */
642 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
643 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
646 /* Set the default focus depending on having already a To: field or not */
647 if ((!to)||(*to == '\0')) {
648 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
650 gtk_widget_grab_focus (priv->msg_body);
653 /* TODO: lower priority, select in the From: combo to the
654 value that comes from msg <- not sure, should it be
657 /* Add attachments to the view */
658 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
659 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
660 if (priv->attachments == NULL) {
661 gtk_widget_hide (priv->attachments_caption);
663 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
664 gtk_widget_show_all (priv->attachments_caption);
667 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
668 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
670 reset_modified (self);
672 update_dimmed (self);
673 text_buffer_can_undo (priv->text_buffer, FALSE, self);
675 priv->draft_msg = g_object_ref(msg);
679 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
682 GList *item_children, *node;
683 GtkWidget *bin_child;
685 bin_child = gtk_bin_get_child (GTK_BIN(item));
687 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
689 for (node = item_children; node != NULL; node = g_list_next (node)) {
690 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
691 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
694 g_list_free (item_children);
698 menu_tool_button_dont_expand (GtkMenuToolButton *item)
701 GList *item_children, *node;
703 box = gtk_bin_get_child (GTK_BIN (item));
704 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
705 item_children = gtk_container_get_children (GTK_CONTAINER (box));
707 for (node = item_children; node != NULL; node = g_list_next (node)) {
708 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
709 if (GTK_IS_TOGGLE_BUTTON (node->data))
710 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
711 else if (GTK_IS_BUTTON (node->data))
712 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
714 g_list_free (item_children);
719 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
721 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
722 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
723 GtkWidget *placeholder;
724 GtkWidget *tool_item;
729 GtkWidget *sizes_menu;
730 GtkWidget *fonts_menu;
731 GSList *radio_group = NULL;
736 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
737 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
739 /* should we hide the toolbar? */
740 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
741 gtk_widget_hide (parent_priv->toolbar);
743 /* Font color placeholder */
744 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
745 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
748 tool_item = GTK_WIDGET (gtk_tool_item_new ());
749 priv->font_color_button = hildon_color_button_new ();
750 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
751 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
752 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
753 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
754 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
755 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
756 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
758 /* Font size and face placeholder */
759 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
760 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
762 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
763 priv->size_tool_button_label = gtk_label_new (NULL);
764 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
765 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
766 size_text,"</span>", NULL);
767 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
769 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
770 sizes_menu = gtk_menu_new ();
771 priv->size_items_group = NULL;
773 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
774 GtkWidget *size_menu_item;
776 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
777 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
778 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
779 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
780 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
781 gtk_widget_show (size_menu_item);
783 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
787 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
788 GtkWidget *item = (GtkWidget *) node->data;
789 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
793 priv->size_items_group = g_slist_reverse (priv->size_items_group);
794 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
795 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
796 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
797 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
798 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
799 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
800 priv->font_size_toolitem = tool_item;
803 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
804 priv->font_tool_button_label = gtk_label_new (NULL);
805 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
806 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
808 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
809 fonts_menu = gtk_menu_new ();
810 priv->font_items_group = NULL;
812 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
813 GtkWidget *font_menu_item;
814 GtkWidget *child_label;
816 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
817 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
818 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
819 wp_get_font_name (font_index), "</span>", NULL);
820 gtk_label_set_markup (GTK_LABEL (child_label), markup);
823 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
824 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
825 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
826 gtk_widget_show (font_menu_item);
828 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
831 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
832 GtkWidget *item = (GtkWidget *) node->data;
833 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
836 priv->font_items_group = g_slist_reverse (priv->font_items_group);
837 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
838 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
839 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
840 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
841 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
842 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
843 priv->font_face_toolitem = tool_item;
845 /* Set expand and homogeneous for remaining items */
846 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
847 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
848 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
849 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
850 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
851 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
852 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
853 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
854 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
862 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name)
865 ModestWindowPrivate *parent_priv;
866 ModestMsgEditWindowPrivate *priv;
867 GtkActionGroup *action_group;
868 GError *error = NULL;
869 GdkPixbuf *window_icon = NULL;
872 gboolean prefer_formatted;
874 ModestPair *account_pair = NULL;
876 g_return_val_if_fail (msg, NULL);
877 g_return_val_if_fail (account_name, NULL);
879 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
881 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
882 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
884 parent_priv->ui_manager = gtk_ui_manager_new();
885 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
886 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
888 /* Add common actions */
889 gtk_action_group_add_actions (action_group,
890 modest_msg_edit_action_entries,
891 G_N_ELEMENTS (modest_msg_edit_action_entries),
893 gtk_action_group_add_toggle_actions (action_group,
894 modest_msg_edit_toggle_action_entries,
895 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
897 gtk_action_group_add_radio_actions (action_group,
898 modest_msg_edit_alignment_radio_action_entries,
899 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
901 G_CALLBACK (modest_ui_actions_on_change_justify),
903 gtk_action_group_add_radio_actions (action_group,
904 modest_msg_edit_zoom_action_entries,
905 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
907 G_CALLBACK (modest_ui_actions_on_change_zoom),
909 gtk_action_group_add_radio_actions (action_group,
910 modest_msg_edit_priority_action_entries,
911 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
913 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
915 gtk_action_group_add_radio_actions (action_group,
916 modest_msg_edit_file_format_action_entries,
917 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
918 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
919 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
921 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
922 g_object_unref (action_group);
924 /* Load the UI definition */
925 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
928 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
929 g_clear_error (&error);
932 /* Add accelerators */
933 gtk_window_add_accel_group (GTK_WINDOW (obj),
934 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
937 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
938 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
941 init_window (MODEST_MSG_EDIT_WINDOW(obj));
943 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
945 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
947 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
949 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
951 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
952 if (account_pair != NULL)
953 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
955 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg);
957 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
959 /* Set window icon */
960 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
961 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
963 /* Dim at start clipboard actions */
964 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
965 gtk_action_set_sensitive (action, FALSE);
966 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
967 gtk_action_set_sensitive (action, FALSE);
968 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
969 gtk_action_set_sensitive (action, FALSE);
971 /* Update select all */
972 update_select_all_dimming (MODEST_MSG_EDIT_WINDOW (obj));
973 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu");
974 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (edit_menu_activated), obj);
975 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu");
976 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (view_menu_activated), obj);
978 /* set initial state of cc and bcc */
979 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
980 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
981 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
982 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
983 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
984 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
986 /* Setup the file format */
987 conf = modest_runtime_get_conf ();
988 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
990 g_clear_error (&error);
991 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
993 file_format = (prefer_formatted) ?
994 MODEST_FILE_FORMAT_FORMATTED_TEXT :
995 MODEST_FILE_FORMAT_PLAIN_TEXT;
996 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
998 update_paste_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1000 return (ModestWindow*) obj;
1004 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1006 GString **string_buffer = (GString **) user_data;
1008 *string_buffer = g_string_append (*string_buffer, buffer);
1014 * @result: A new string which should be freed with g_free().
1017 get_formatted_data (ModestMsgEditWindow *edit_window)
1019 ModestMsgEditWindowPrivate *priv;
1020 GString *string_buffer = g_string_new ("");
1022 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1024 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1026 return g_string_free (string_buffer, FALSE);
1031 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1034 const gchar *account_name;
1035 ModestMsgEditWindowPrivate *priv;
1037 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1039 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1041 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1042 g_return_val_if_fail (account_name, NULL);
1045 /* don't free these (except from) */
1046 data = g_slice_new0 (MsgData);
1047 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1049 data->account_name = g_strdup (account_name);
1050 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1051 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1052 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1053 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1054 if (priv->draft_msg) {
1055 data->draft_msg = g_object_ref (priv->draft_msg);
1057 data->draft_msg = NULL;
1060 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1062 gtk_text_buffer_get_bounds (buf, &b, &e);
1063 data->plain_body = g_strdup (gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE)); /* returns a copy */
1065 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1066 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1068 data->html_body = NULL;
1070 data->attachments = priv->attachments; /* TODO: copy and free ? */
1071 data->priority_flags = priv->priority_flags;
1076 /* TODO: We must duplicate this implementation for GNOME and Maemo, but that is unwise. */
1078 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1081 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1089 g_free (data->subject);
1090 g_free (data->plain_body);
1091 g_free (data->html_body);
1092 g_free (data->account_name);
1094 if (data->draft_msg != NULL) {
1095 g_object_unref (data->draft_msg);
1096 data->draft_msg = NULL;
1099 g_list_foreach (data->attachments, (GFunc)g_free, NULL);
1100 g_list_free (data->attachments);
1102 /* TODO: Free data->attachments? */
1104 g_slice_free (MsgData, data);
1108 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1111 ModestMsgEditWindowPrivate *priv = NULL;
1112 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1114 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1116 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1118 return MODEST_MSG_EDIT_FORMAT_HTML;
1120 return MODEST_MSG_EDIT_FORMAT_TEXT;
1124 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1125 ModestMsgEditFormat format)
1127 ModestMsgEditWindowPrivate *priv;
1129 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1130 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1133 case MODEST_MSG_EDIT_FORMAT_HTML:
1134 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1136 case MODEST_MSG_EDIT_FORMAT_TEXT:
1137 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1140 g_return_if_reached ();
1144 ModestMsgEditFormatState *
1145 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1147 ModestMsgEditFormatState *format_state = NULL;
1148 ModestMsgEditWindowPrivate *priv;
1149 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1151 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1152 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1154 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1156 format_state = g_new0 (ModestMsgEditFormatState, 1);
1157 format_state->bold = buffer_format->bold&0x1;
1158 format_state->italics = buffer_format->italic&0x1;
1159 format_state->bullet = buffer_format->bullet&0x1;
1160 format_state->color = buffer_format->color;
1161 format_state->font_size = buffer_format->font_size;
1162 format_state->font_family = wp_get_font_name (buffer_format->font);
1163 format_state->justification = buffer_format->justification;
1164 g_free (buffer_format);
1166 return format_state;
1171 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1172 const ModestMsgEditFormatState *format_state)
1174 ModestMsgEditWindowPrivate *priv;
1175 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1176 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1177 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1178 g_return_if_fail (format_state != NULL);
1180 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1181 gtk_widget_grab_focus (priv->msg_body);
1182 buffer_format->bold = (format_state->bold != FALSE);
1183 buffer_format->italic = (format_state->italics != FALSE);
1184 buffer_format->color = format_state->color;
1185 buffer_format->font_size = format_state->font_size;
1186 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1187 buffer_format->justification = format_state->justification;
1188 buffer_format->bullet = format_state->bullet;
1190 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1192 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1193 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1194 buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
1195 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1196 buffer_format->cs.font = (buffer_format->font != current_format->font);
1197 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1198 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1200 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1201 if (buffer_format->cs.bold) {
1202 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1204 if (buffer_format->cs.italic) {
1205 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1207 if (buffer_format->cs.color) {
1208 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1210 if (buffer_format->cs.font_size) {
1211 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1213 if (buffer_format->cs.justification) {
1214 switch (buffer_format->justification) {
1215 case GTK_JUSTIFY_LEFT:
1216 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1218 case GTK_JUSTIFY_CENTER:
1219 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1221 case GTK_JUSTIFY_RIGHT:
1222 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1229 if (buffer_format->cs.font) {
1230 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1232 if (buffer_format->cs.bullet) {
1233 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((int)buffer_format->bullet));
1235 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1236 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1238 g_free (current_format);
1243 toggle_action_set_active_block_notify (GtkToggleAction *action,
1246 GSList *proxies = NULL;
1248 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1249 proxies != NULL; proxies = g_slist_next (proxies)) {
1250 GtkWidget *widget = (GtkWidget *) proxies->data;
1251 gtk_action_block_activate_from (GTK_ACTION (action), widget);
1254 gtk_toggle_action_set_active (action, value);
1256 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1257 proxies != NULL; proxies = g_slist_next (proxies)) {
1258 GtkWidget *widget = (GtkWidget *) proxies->data;
1259 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
1264 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1266 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1268 ModestWindowPrivate *parent_priv;
1269 ModestMsgEditWindowPrivate *priv;
1270 GtkWidget *new_size_menuitem;
1271 GtkWidget *new_font_menuitem;
1273 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1274 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1276 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1277 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1278 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1279 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1281 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1282 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1283 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1286 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1288 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1289 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1291 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1292 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1294 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1295 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1297 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1298 G_CALLBACK (modest_msg_edit_window_color_button_change),
1300 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1301 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1302 G_CALLBACK (modest_msg_edit_window_color_button_change),
1305 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1306 buffer_format->font_size))->data);
1307 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1311 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1312 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1313 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1315 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1316 G_CALLBACK (modest_msg_edit_window_size_change),
1318 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1319 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1320 G_CALLBACK (modest_msg_edit_window_size_change),
1324 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1325 buffer_format->font))->data);
1326 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1330 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1331 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1332 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1334 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1335 G_CALLBACK (modest_msg_edit_window_font_change),
1337 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1338 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1339 G_CALLBACK (modest_msg_edit_window_font_change),
1343 g_free (buffer_format);
1349 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1352 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1353 ModestMsgEditWindowPrivate *priv;
1354 GtkWidget *dialog = NULL;
1356 const GdkColor *new_color = NULL;
1358 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1359 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1361 #ifdef MODEST_HILDON_VERSION_0
1362 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1363 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1365 dialog = hildon_color_chooser_new ();
1366 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1367 #endif /*MODEST_HILDON_VERSION_0*/
1368 g_free (buffer_format);
1370 response = gtk_dialog_run (GTK_DIALOG (dialog));
1372 case GTK_RESPONSE_OK: {
1373 #ifdef MODEST_HILDON_VERSION_0
1374 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1377 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1379 #endif /*MODEST_HILDON_VERSION_0*/
1386 gtk_widget_destroy (dialog);
1388 if (new_color != NULL)
1389 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1394 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1397 ModestMsgEditWindowPrivate *priv;
1398 GtkWidget *dialog = NULL;
1400 GdkColor *old_color = NULL;
1401 const GdkColor *new_color = NULL;
1403 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1404 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1406 #ifdef MODEST_HILDON_VERSION_0
1407 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1408 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1410 dialog = hildon_color_chooser_new ();
1411 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1412 #endif /*MODEST_HILDON_VERSION_9*/
1414 response = gtk_dialog_run (GTK_DIALOG (dialog));
1416 case GTK_RESPONSE_OK: {
1417 #ifdef MODEST_HILDON_VERSION_0
1418 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1421 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1423 #endif /*MODEST_HILDON_VERSION_0*/
1429 gtk_widget_destroy (dialog);
1431 if (new_color != NULL)
1432 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1438 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1441 ModestMsgEditWindowPrivate *priv;
1442 GtkWidget *dialog = NULL;
1444 GSList *uris = NULL;
1445 GSList *uri_node = NULL;
1447 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1449 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1450 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1451 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1453 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1455 response = gtk_dialog_run (GTK_DIALOG (dialog));
1457 case GTK_RESPONSE_OK:
1458 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1463 gtk_widget_destroy (dialog);
1465 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1467 GnomeVFSHandle *handle = NULL;
1468 GnomeVFSResult result;
1469 GtkTextIter position;
1470 GtkTextMark *insert_mark;
1472 uri = (const gchar *) uri_node->data;
1473 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1474 if (result == GNOME_VFS_OK) {
1475 GdkPixbufLoader *loader;
1477 GnomeVFSFileInfo info;
1478 gchar *filename, *basename;
1479 TnyMimePart *mime_part;
1482 const gchar *mime_type = NULL;
1484 filename = g_filename_from_uri (uri, NULL, NULL);
1485 if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
1487 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1489 mime_part = tny_platform_factory_new_mime_part
1490 (modest_runtime_get_platform_factory ());
1491 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1493 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1495 content_id = g_strdup_printf ("%d", priv->last_cid);
1496 tny_mime_part_set_content_id (mime_part, content_id);
1497 g_free (content_id);
1500 basename = g_path_get_basename (filename);
1501 tny_mime_part_set_filename (mime_part, basename);
1504 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1505 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1507 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1508 gtk_widget_show_all (priv->attachments_caption);
1509 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1512 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1513 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1514 unsigned char read_buffer[128];
1516 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1517 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
1520 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1521 g_object_ref (pixbuf);
1522 gdk_pixbuf_loader_close (loader, NULL);
1523 g_object_unref (loader);
1525 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1526 GdkPixbuf *new_pixbuf;
1528 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1529 gdk_pixbuf_get_width (pixbuf);
1530 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1531 g_object_unref (pixbuf);
1532 pixbuf = new_pixbuf;
1535 if (pixbuf != NULL) {
1536 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1537 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1538 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1547 modest_msg_edit_window_attach_file (ModestMsgEditWindow *window)
1550 ModestMsgEditWindowPrivate *priv;
1551 GtkWidget *dialog = NULL;
1553 GSList *uris = NULL;
1556 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1558 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1559 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1561 response = gtk_dialog_run (GTK_DIALOG (dialog));
1563 case GTK_RESPONSE_OK:
1564 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1569 gtk_widget_destroy (dialog);
1571 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1573 GnomeVFSHandle *handle = NULL;
1574 GnomeVFSResult result;
1576 uri = (const gchar *) uri_node->data;
1577 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1578 if (result == GNOME_VFS_OK) {
1579 TnyMimePart *mime_part;
1581 const gchar *mime_type = NULL;
1585 GnomeVFSFileInfo info;
1587 filename = g_filename_from_uri (uri, NULL, NULL);
1589 if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE) == GNOME_VFS_OK)
1590 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1591 mime_part = tny_platform_factory_new_mime_part
1592 (modest_runtime_get_platform_factory ());
1593 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1595 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1597 content_id = g_strdup_printf ("%d", priv->last_cid);
1598 tny_mime_part_set_content_id (mime_part, content_id);
1599 g_free (content_id);
1602 basename = g_path_get_basename (filename);
1603 tny_mime_part_set_filename (mime_part, basename);
1606 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1607 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1609 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1610 gtk_widget_show_all (priv->attachments_caption);
1611 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1616 g_slist_foreach (uris, (GFunc) g_free, NULL);
1617 g_slist_free (uris);
1621 modest_msg_edit_window_attach_file_noninteractive (
1622 ModestMsgEditWindow *window,
1623 const gchar *file_uri)
1626 ModestMsgEditWindowPrivate *priv;
1628 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1630 if (file_uri && strlen(file_uri)) {
1633 /* TODO: We should probably try to use only the URI,
1634 * instead of using a filename.
1636 gchar* filename = g_filename_from_uri (file_uri, NULL, NULL);
1638 g_warning("%s: g_filename_from_uri('%s') failed.\n", __FUNCTION__, file_uri);
1641 file_id = g_open (filename, O_RDONLY, 0);
1642 if (file_id != -1) {
1643 TnyMimePart *mime_part;
1645 const gchar *mime_type;
1648 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1649 mime_type = gnome_vfs_get_mime_type(filename);
1651 mime_type = gnome_vfs_get_file_mime_type_fast (filename, NULL);
1653 mime_part = tny_platform_factory_new_mime_part
1654 (modest_runtime_get_platform_factory ());
1655 stream = TNY_STREAM (tny_fs_stream_new (file_id));
1657 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1659 content_id = g_strdup_printf ("%d", priv->last_cid);
1660 tny_mime_part_set_content_id (mime_part, content_id);
1661 g_free (content_id);
1664 basename = g_path_get_basename (filename);
1665 tny_mime_part_set_filename (mime_part, basename);
1668 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1669 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1671 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1672 gtk_widget_show_all (priv->attachments_caption);
1673 } else if (file_id == -1) {
1675 g_warning("file to be attached does not exist: %s", filename);
1683 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1686 ModestMsgEditWindowPrivate *priv;
1687 gboolean clean_list = FALSE;
1689 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1690 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1692 if (att_list == NULL) {
1693 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1697 if (att_list == NULL) {
1698 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1700 GtkWidget *confirmation_dialog = NULL;
1701 gboolean dialog_response;
1703 gchar *message = NULL;
1704 const gchar *filename = NULL;
1706 if (att_list->next == NULL) {
1707 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1711 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1712 att_list->next == NULL), filename);
1713 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1715 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1716 gtk_widget_destroy (confirmation_dialog);
1717 if (!dialog_response) {
1719 g_list_free (att_list);
1722 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1724 for (node = att_list; node != NULL; node = g_list_next (node)) {
1725 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1726 const gchar *att_id;
1727 priv->attachments = g_list_remove (priv->attachments, mime_part);
1729 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1731 if (priv->attachments == NULL)
1732 gtk_widget_hide (priv->attachments_caption);
1733 att_id = tny_mime_part_get_content_id (mime_part);
1735 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1737 g_object_unref (mime_part);
1738 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1743 g_list_free (att_list);
1747 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1750 ModestMsgEditWindowPrivate *priv;
1751 GdkColor *new_color;
1752 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1754 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1755 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1758 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1760 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1762 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1764 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1769 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1772 ModestMsgEditWindowPrivate *priv;
1773 gint new_size_index;
1774 ModestMsgEditWindow *window;
1777 window = MODEST_MSG_EDIT_WINDOW (userdata);
1778 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1779 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1781 if (gtk_check_menu_item_get_active (menu_item)) {
1783 WPTextBufferFormat format;
1785 memset (&format, 0, sizeof (format));
1786 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1788 label = gtk_bin_get_child (GTK_BIN (menu_item));
1790 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1791 format.cs.font_size = TRUE;
1792 format.cs.text_position = TRUE;
1793 format.cs.font = TRUE;
1794 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1795 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1797 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1798 (gpointer) wp_get_font_size_index (new_size_index, 12)))
1799 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1801 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1802 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1803 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1809 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1812 ModestMsgEditWindowPrivate *priv;
1813 gint new_font_index;
1814 ModestMsgEditWindow *window;
1817 window = MODEST_MSG_EDIT_WINDOW (userdata);
1818 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1819 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1821 if (gtk_check_menu_item_get_active (menu_item)) {
1824 label = gtk_bin_get_child (GTK_BIN (menu_item));
1826 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1828 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1829 (gpointer) new_font_index))
1830 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1832 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1833 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1834 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1840 modest_msg_edit_window_set_zoom (ModestWindow *window,
1843 ModestMsgEditWindowPrivate *priv;
1844 ModestWindowPrivate *parent_priv;
1845 GtkRadioAction *zoom_radio_action;
1847 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1849 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1850 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1851 priv->zoom_level = zoom;
1852 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom);
1854 /* Zoom level menu options should be updated with the current zoom level */
1855 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1856 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1857 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1858 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1859 /* FIXME: Not availible before Gtk 2.10 */
1861 gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
1866 modest_msg_edit_window_get_zoom (ModestWindow *window)
1868 ModestMsgEditWindowPrivate *priv;
1870 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1872 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1873 return priv->zoom_level;
1877 zoom_allowed (ModestMsgEditWindow *window)
1881 focus = gtk_window_get_focus (GTK_WINDOW (window));
1882 return (focus != NULL && WP_IS_TEXT_VIEW (focus));
1886 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1888 ModestWindowPrivate *parent_priv;
1889 GtkRadioAction *zoom_radio_action;
1890 GSList *group, *node;
1892 /* First we check if the text view is focused. If not, zooming is not allowed */
1893 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1894 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1898 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1899 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1900 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1902 group = gtk_radio_action_get_group (zoom_radio_action);
1904 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1905 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
1909 for (node = group; node != NULL; node = g_slist_next (node)) {
1910 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1911 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1919 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1921 ModestWindowPrivate *parent_priv;
1922 GtkRadioAction *zoom_radio_action;
1923 GSList *group, *node;
1925 /* First we check if the text view is focused. If not, zooming is not allowed */
1926 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1927 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1931 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1932 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1933 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1935 group = gtk_radio_action_get_group (zoom_radio_action);
1937 for (node = group; node != NULL; node = g_slist_next (node)) {
1938 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1939 if (node->next != NULL) {
1940 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1943 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
1951 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1953 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1954 ModestWindowPrivate *parent_priv;
1955 ModestWindowMgr *mgr;
1956 gboolean is_fullscreen;
1957 GtkAction *fs_toggle_action;
1960 mgr = modest_runtime_get_window_mgr ();
1961 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1963 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1965 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1966 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1967 if (is_fullscreen != active)
1968 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1976 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
1978 ModestWindowPrivate *parent_priv;
1979 GtkAction *fs_toggle_action;
1982 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1984 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1985 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
1986 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
1990 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
1993 ModestMsgEditWindowPrivate *priv = NULL;
1994 const gchar *recipients;
1995 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1997 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1998 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1999 recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field));
2000 if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2001 gtk_widget_show (priv->cc_caption);
2003 gtk_widget_hide (priv->cc_caption);
2004 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2008 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2011 ModestMsgEditWindowPrivate *priv = NULL;
2012 const gchar *recipients;
2013 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2015 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2016 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2017 recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field));
2018 if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2019 gtk_widget_show (priv->bcc_caption);
2021 gtk_widget_hide (priv->bcc_caption);
2022 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2026 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2027 ModestRecptEditor *editor)
2029 ModestMsgEditWindowPrivate *priv;
2031 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2032 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2033 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2035 if (editor == NULL) {
2036 GtkWidget *view_focus;
2037 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2039 /* This code should be kept in sync with ModestRecptEditor. The
2040 textview inside the recpt editor is the one that really gets the
2041 focus. As it's inside a scrolled window, and this one inside the
2042 hbox recpt editor inherits from, we'll need to go up in the
2043 hierarchy to know if the text view is part of the recpt editor
2044 or if it's a different text entry */
2046 if (gtk_widget_get_parent (view_focus)) {
2047 GtkWidget *first_parent;
2049 first_parent = gtk_widget_get_parent (view_focus);
2050 if (gtk_widget_get_parent (first_parent) &&
2051 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2052 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2057 editor = MODEST_RECPT_EDITOR (priv->to_field);
2061 modest_address_book_select_addresses (editor);
2066 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2068 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2070 modest_msg_edit_window_open_addressbook (window, NULL);
2074 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2075 gboolean show_toolbar)
2077 ModestWindowPrivate *parent_priv;
2079 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2080 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2082 /* FIXME: we can not just use the code of
2083 modest_msg_edit_window_setup_toolbar because it has a
2084 mixture of both initialization and creation code. */
2087 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2089 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2093 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2094 TnyHeaderFlags priority_flags)
2096 ModestMsgEditWindowPrivate *priv;
2097 ModestWindowPrivate *parent_priv;
2099 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2101 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2102 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2103 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2105 if (priv->priority_flags != priority_flags) {
2106 GtkAction *priority_action = NULL;
2108 priv->priority_flags = priority_flags;
2110 switch (priority_flags) {
2111 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2112 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2113 gtk_widget_show (priv->priority_icon);
2114 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2115 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2117 case TNY_HEADER_FLAG_LOW_PRIORITY:
2118 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2119 gtk_widget_show (priv->priority_icon);
2120 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2121 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2124 gtk_widget_hide (priv->priority_icon);
2125 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2126 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2129 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2130 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2135 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2138 ModestMsgEditWindowPrivate *priv;
2139 ModestWindowPrivate *parent_priv;
2140 gint current_format;
2142 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2144 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2145 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2147 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2148 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2150 if (current_format != file_format) {
2151 switch (file_format) {
2152 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2153 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2155 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2159 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2160 response = gtk_dialog_run (GTK_DIALOG (dialog));
2161 gtk_widget_destroy (dialog);
2162 if (response == GTK_RESPONSE_OK) {
2163 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2165 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2166 toggle_action_set_active_block_notify (action, TRUE);
2171 update_dimmed (window);
2176 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2179 ModestMsgEditWindowPrivate *priv;
2180 WPTextBufferFormat oldfmt, fmt;
2181 gint old_position = 0;
2185 GdkColor *color = NULL;
2186 gboolean bold, bold_set, italic, italic_set;
2187 gboolean underline, underline_set;
2188 gboolean strikethrough, strikethrough_set;
2189 gboolean position_set;
2190 gboolean font_size_set, font_set, color_set;
2193 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2194 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2196 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2198 /* First we get the currently selected font information */
2199 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2200 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2202 switch (oldfmt.text_position) {
2203 case TEXT_POSITION_NORMAL:
2206 case TEXT_POSITION_SUPERSCRIPT:
2214 g_object_set (G_OBJECT (dialog),
2215 "bold", oldfmt.bold != FALSE,
2216 "bold-set", !oldfmt.cs.bold,
2217 "underline", oldfmt.underline != FALSE,
2218 "underline-set", !oldfmt.cs.underline,
2219 "italic", oldfmt.italic != FALSE,
2220 "italic-set", !oldfmt.cs.italic,
2221 "strikethrough", oldfmt.strikethrough != FALSE,
2222 "strikethrough-set", !oldfmt.cs.strikethrough,
2223 "color", &oldfmt.color,
2224 "color-set", !oldfmt.cs.color,
2225 "size", wp_font_size[oldfmt.font_size],
2226 "size-set", !oldfmt.cs.font_size,
2227 "position", old_position,
2228 "position-set", !oldfmt.cs.text_position,
2229 "family", wp_get_font_name (oldfmt.font),
2230 "family-set", !oldfmt.cs.font,
2233 gtk_widget_show_all (dialog);
2234 response = gtk_dialog_run (GTK_DIALOG (dialog));
2235 if (response == GTK_RESPONSE_OK) {
2237 g_object_get( dialog,
2239 "bold-set", &bold_set,
2240 "underline", &underline,
2241 "underline-set", &underline_set,
2243 "italic-set", &italic_set,
2244 "strikethrough", &strikethrough,
2245 "strikethrough-set", &strikethrough_set,
2247 "color-set", &color_set,
2249 "size-set", &font_size_set,
2250 "family", &font_name,
2251 "family-set", &font_set,
2252 "position", &position,
2253 "position-set", &position_set,
2258 if (response == GTK_RESPONSE_OK) {
2259 memset(&fmt, 0, sizeof(fmt));
2265 fmt.italic = italic;
2266 fmt.cs.italic = TRUE;
2268 if (underline_set) {
2269 fmt.underline = underline;
2270 fmt.cs.underline = TRUE;
2272 if (strikethrough_set) {
2273 fmt.strikethrough = strikethrough;
2274 fmt.cs.strikethrough = TRUE;
2279 ? TEXT_POSITION_NORMAL
2280 : ( ( position == 1 )
2281 ? TEXT_POSITION_SUPERSCRIPT
2282 : TEXT_POSITION_SUBSCRIPT );
2283 fmt.cs.text_position = TRUE;
2287 fmt.cs.color = TRUE;
2290 fmt.font = wp_get_font_index(font_name,
2295 if (font_size_set) {
2296 fmt.font_size = wp_get_font_size_index(
2297 font_size, DEFAULT_FONT_SIZE);
2298 fmt.cs.font_size = TRUE;
2300 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2302 gtk_widget_destroy (dialog);
2304 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2308 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2310 ModestMsgEditWindowPrivate *priv;
2312 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2313 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2315 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2317 update_dimmed (window);
2322 update_dimmed (ModestMsgEditWindow *window)
2324 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2325 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2329 gboolean editor_focused;
2331 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2332 editor_focused = gtk_widget_is_focus (priv->msg_body);
2334 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2335 gtk_action_set_sensitive (action, rich_text && editor_focused);
2336 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2337 gtk_action_set_sensitive (action, rich_text && editor_focused);
2338 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2339 gtk_action_set_sensitive (action, rich_text && editor_focused);
2340 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2341 gtk_action_set_sensitive (action, rich_text && editor_focused);
2342 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2343 gtk_action_set_sensitive (action, rich_text && editor_focused);
2344 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2345 gtk_action_set_sensitive (action, rich_text && editor_focused);
2346 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2347 gtk_action_set_sensitive (action, rich_text && editor_focused);
2348 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2349 gtk_action_set_sensitive (action, rich_text && editor_focused);
2350 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2351 gtk_action_set_sensitive (action, rich_text && editor_focused);
2352 widget = priv->font_color_button;
2353 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2354 widget = priv->font_size_toolitem;
2355 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2356 widget = priv->font_face_toolitem;
2357 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2361 setup_insensitive_handlers (ModestMsgEditWindow *window)
2363 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2364 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2367 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2368 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2369 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2370 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2372 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2373 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2374 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2375 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2376 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2377 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2378 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2379 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2380 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2381 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2382 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2383 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2384 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2385 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2386 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2387 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2388 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2389 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2390 widget = priv->font_color_button;
2391 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2392 widget = priv->font_size_toolitem;
2393 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2394 widget = priv->font_face_toolitem;
2395 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2397 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2398 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (remove_attachment_insensitive_press), window);
2399 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2400 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (zoom_insensitive_press), window);
2402 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2403 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (paste_insensitive_press), window);
2404 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2405 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (copy_insensitive_press), window);
2409 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2411 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2414 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2415 gtk_action_set_sensitive (action, can_undo);
2419 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2422 GtkTextIter match_start, match_end;
2424 if (image_id == NULL)
2427 gtk_text_buffer_get_start_iter (buffer, &iter);
2429 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2430 GSList *tags = gtk_text_iter_get_tags (&match_start);
2432 for (node = tags; node != NULL; node = g_slist_next (node)) {
2433 GtkTextTag *tag = (GtkTextTag *) node->data;
2434 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2435 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2436 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2438 offset = gtk_text_iter_get_offset (&match_start);
2439 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2440 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2444 gtk_text_iter_forward_char (&iter);
2449 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2451 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2452 GtkTextIter real_start, real_end;
2453 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2455 if (gtk_text_iter_compare (start, end) > 0) {
2459 real_start = *start;
2463 GSList *tags = gtk_text_iter_get_tags (&real_start);
2465 for (node = tags; node != NULL; node = g_slist_next (node)) {
2466 GtkTextTag *tag = (GtkTextTag *) node->data;
2467 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2468 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2470 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2472 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2475 } while (gtk_text_iter_forward_char (&real_start)&&
2476 (gtk_text_iter_compare (&real_start, &real_end)<=0));
2480 msg_body_focus (GtkWidget *focus,
2481 GdkEventFocus *event,
2485 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2490 recpt_field_changed (GtkTextBuffer *buffer,
2491 ModestMsgEditWindow *editor)
2493 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2494 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2495 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2496 gboolean dim = FALSE;
2499 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2500 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2501 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2503 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2504 gtk_text_buffer_get_char_count (cc_buffer) +
2505 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2507 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2508 gtk_action_set_sensitive (action, !dim);
2509 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2510 gtk_action_set_sensitive (action, !dim);
2514 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2516 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2520 zoom_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2522 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2526 remove_attachment_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2528 ModestWindowPrivate *parent_priv;
2529 ModestMsgEditWindowPrivate *priv;
2530 GList *selected_attachments = NULL;
2531 gint n_att_selected = 0;
2533 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2534 parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2536 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2537 n_att_selected = g_list_length (selected_attachments);
2538 g_list_free (selected_attachments);
2540 if (n_att_selected > 1)
2541 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unable_to_display_more"));
2542 else if (n_att_selected == 0)
2543 hildon_banner_show_information (NULL, NULL, _("TODO: select one attachment"));
2545 hildon_banner_show_information (NULL, NULL, _("mail_ib_unable_to_purge_attachments"));
2549 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2551 gboolean rich_text, editor_focused;
2553 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2554 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2555 editor_focused = gtk_widget_is_focus (priv->msg_body);
2558 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2559 else if (!editor_focused)
2560 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2564 reset_modified (ModestMsgEditWindow *editor)
2566 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2567 GtkTextBuffer *buffer;
2569 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2570 gtk_text_buffer_set_modified (buffer, FALSE);
2571 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2572 gtk_text_buffer_set_modified (buffer, FALSE);
2573 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2574 gtk_text_buffer_set_modified (buffer, FALSE);
2575 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2579 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2581 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2582 GtkTextBuffer *buffer;
2584 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2585 if (gtk_text_buffer_get_modified (buffer))
2587 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2588 if (gtk_text_buffer_get_modified (buffer))
2590 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2591 if (gtk_text_buffer_get_modified (buffer))
2593 if (gtk_text_buffer_get_modified (priv->text_buffer))
2600 modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
2602 ModestMsgEditWindowPrivate *priv = NULL;
2604 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2605 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2607 /* check if there's no recipient added */
2608 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2609 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2610 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2611 /* no recipient contents, then select contacts */
2612 modest_msg_edit_window_open_addressbook (window, NULL);
2616 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
2618 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
2620 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
2623 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2630 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2631 ModestMsgEditWindow *window)
2633 modest_msg_edit_window_attach_file (window);
2637 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2639 ModestMsgEditWindow *window)
2641 ModestWindowPrivate *parent_priv;
2642 ModestMsgEditWindowPrivate *priv;
2646 GList *selected_attachments = NULL;
2647 gint n_att_selected = 0;
2649 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2650 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2651 selection = gtk_clipboard_wait_for_text (clipboard);
2652 focused = gtk_window_get_focus (GTK_WINDOW (window));
2654 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2655 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2656 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2657 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2659 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2660 n_att_selected = g_list_length (selected_attachments);
2661 g_list_free (selected_attachments);
2663 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2664 gtk_action_set_sensitive (action, n_att_selected == 1);
2667 update_paste_dimming (window);
2671 update_window_title (ModestMsgEditWindow *window)
2673 ModestMsgEditWindowPrivate *priv = NULL;
2674 const gchar *subject;
2676 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2677 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2678 if (subject == NULL || subject[0] == '\0')
2679 subject = _("mail_va_new_email");
2681 gtk_window_set_title (GTK_WINDOW (window), subject);
2686 subject_field_changed (GtkEditable *editable,
2687 ModestMsgEditWindow *window)
2689 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2690 update_window_title (window);
2691 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2695 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2698 ModestMsgEditWindowPrivate *priv = NULL;
2700 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2701 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2703 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2705 gtk_widget_show_all (priv->find_toolbar);
2706 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2708 gtk_widget_hide_all (priv->find_toolbar);
2709 gtk_widget_grab_focus (priv->msg_body);
2715 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2717 GtkTextIter *match_start,
2718 GtkTextIter *match_end)
2720 GtkTextIter end_iter;
2721 gchar *str_casefold;
2724 gchar *range_casefold;
2727 gboolean result = FALSE;
2734 gtk_text_iter_forward_to_end (&end_iter);
2736 str_casefold = g_utf8_casefold (str, -1);
2737 str_chars_n = strlen (str);
2739 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2740 range_casefold = g_utf8_casefold (range_text, -1);
2741 range_chars_n = strlen (range_casefold);
2743 if (range_chars_n < str_chars_n) {
2744 g_free (str_casefold);
2745 g_free (range_text);
2746 g_free (range_casefold);
2750 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2751 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2752 if (!g_utf8_collate (range_subtext, str_casefold)) {
2753 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2755 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2756 match_start, match_end, NULL);
2757 g_free (found_text);
2759 g_free (range_subtext);
2763 g_free (str_casefold);
2764 g_free (range_text);
2765 g_free (range_casefold);
2772 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2773 ModestMsgEditWindow *window)
2775 gchar *current_search = NULL;
2776 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2778 GtkTextIter selection_start, selection_end;
2779 GtkTextIter match_start, match_end;
2780 gboolean continue_search = FALSE;
2782 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2783 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2784 g_free (current_search);
2785 g_free (priv->last_search);
2786 priv->last_search = NULL;
2787 /* Information banner about empty search */
2788 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2792 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2793 continue_search = TRUE;
2795 g_free (priv->last_search);
2796 priv->last_search = g_strdup (current_search);
2799 if (continue_search) {
2800 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2801 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2802 &match_start, &match_end);
2804 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2806 GtkTextIter buffer_start;
2807 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2808 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2809 &match_start, &match_end);
2811 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2814 /* Mark as selected the string found in search */
2816 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2817 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2819 g_free (priv->last_search);
2820 priv->last_search = NULL;
2822 g_free (current_search);
2826 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2827 ModestMsgEditWindow *window)
2829 GtkToggleAction *toggle;
2830 ModestWindowPrivate *parent_priv;
2831 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2833 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2834 gtk_toggle_action_set_active (toggle, FALSE);
2839 update_paste_dimming (ModestMsgEditWindow *window)
2841 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2842 GtkAction *action = NULL;
2843 GtkClipboard *clipboard = NULL;
2847 focused = gtk_window_get_focus (GTK_WINDOW (window));
2849 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2850 active = gtk_clipboard_wait_is_text_available (clipboard);
2853 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2857 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2858 gtk_action_set_sensitive (action, active);
2863 paste_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2865 GtkWidget *focused = gtk_window_get_focus (GTK_WINDOW (editor));
2867 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2868 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_unable_to_paste_here"));
2870 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ecoc_ib_edwin_nothing_to_paste"));
2875 copy_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2877 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_unable_to_copy"));
2883 modest_msg_edit_window_system_clipboard_owner_change (GtkClipboard *clipboard,
2885 ModestMsgEditWindow *window)
2887 update_paste_dimming (window);
2891 update_select_all_dimming (ModestMsgEditWindow *window)
2894 gboolean dimmed = FALSE;
2896 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2898 focused = gtk_window_get_focus (GTK_WINDOW (window));
2899 if (GTK_IS_ENTRY (focused)) {
2900 const gchar *current_text;
2901 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
2902 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
2903 } else if (GTK_IS_TEXT_VIEW (focused)) {
2904 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
2905 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
2906 } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
2909 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
2910 gtk_action_set_sensitive (action, !dimmed);
2914 update_zoom_dimming (ModestMsgEditWindow *window)
2917 gboolean dimmed = FALSE;
2919 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2921 focused = gtk_window_get_focus (GTK_WINDOW (window));
2922 dimmed = ! WP_IS_TEXT_VIEW (focused);
2923 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2924 gtk_action_set_sensitive (action, !dimmed);
2928 edit_menu_activated (GtkAction *action,
2931 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2933 update_select_all_dimming (window);
2936 view_menu_activated (GtkAction *action,
2939 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2941 update_zoom_dimming (window);
2945 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
2947 ModestMsgEditWindowPrivate *priv;
2949 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
2954 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
2957 ModestMsgEditWindowPrivate *priv;
2959 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);