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 gint current_format;
2141 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2143 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2145 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2146 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2148 if (current_format != file_format) {
2149 switch (file_format) {
2150 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2151 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2153 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2157 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2158 response = gtk_dialog_run (GTK_DIALOG (dialog));
2159 gtk_widget_destroy (dialog);
2160 if (response == GTK_RESPONSE_OK)
2161 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2165 update_dimmed (window);
2170 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2173 ModestMsgEditWindowPrivate *priv;
2174 WPTextBufferFormat oldfmt, fmt;
2175 gint old_position = 0;
2179 GdkColor *color = NULL;
2180 gboolean bold, bold_set, italic, italic_set;
2181 gboolean underline, underline_set;
2182 gboolean strikethrough, strikethrough_set;
2183 gboolean position_set;
2184 gboolean font_size_set, font_set, color_set;
2187 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2188 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2190 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2192 /* First we get the currently selected font information */
2193 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2194 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2196 switch (oldfmt.text_position) {
2197 case TEXT_POSITION_NORMAL:
2200 case TEXT_POSITION_SUPERSCRIPT:
2208 g_object_set (G_OBJECT (dialog),
2209 "bold", oldfmt.bold != FALSE,
2210 "bold-set", !oldfmt.cs.bold,
2211 "underline", oldfmt.underline != FALSE,
2212 "underline-set", !oldfmt.cs.underline,
2213 "italic", oldfmt.italic != FALSE,
2214 "italic-set", !oldfmt.cs.italic,
2215 "strikethrough", oldfmt.strikethrough != FALSE,
2216 "strikethrough-set", !oldfmt.cs.strikethrough,
2217 "color", &oldfmt.color,
2218 "color-set", !oldfmt.cs.color,
2219 "size", wp_font_size[oldfmt.font_size],
2220 "size-set", !oldfmt.cs.font_size,
2221 "position", old_position,
2222 "position-set", !oldfmt.cs.text_position,
2223 "family", wp_get_font_name (oldfmt.font),
2224 "family-set", !oldfmt.cs.font,
2227 gtk_widget_show_all (dialog);
2228 response = gtk_dialog_run (GTK_DIALOG (dialog));
2229 if (response == GTK_RESPONSE_OK) {
2231 g_object_get( dialog,
2233 "bold-set", &bold_set,
2234 "underline", &underline,
2235 "underline-set", &underline_set,
2237 "italic-set", &italic_set,
2238 "strikethrough", &strikethrough,
2239 "strikethrough-set", &strikethrough_set,
2241 "color-set", &color_set,
2243 "size-set", &font_size_set,
2244 "family", &font_name,
2245 "family-set", &font_set,
2246 "position", &position,
2247 "position-set", &position_set,
2252 if (response == GTK_RESPONSE_OK) {
2253 memset(&fmt, 0, sizeof(fmt));
2259 fmt.italic = italic;
2260 fmt.cs.italic = TRUE;
2262 if (underline_set) {
2263 fmt.underline = underline;
2264 fmt.cs.underline = TRUE;
2266 if (strikethrough_set) {
2267 fmt.strikethrough = strikethrough;
2268 fmt.cs.strikethrough = TRUE;
2273 ? TEXT_POSITION_NORMAL
2274 : ( ( position == 1 )
2275 ? TEXT_POSITION_SUPERSCRIPT
2276 : TEXT_POSITION_SUBSCRIPT );
2277 fmt.cs.text_position = TRUE;
2281 fmt.cs.color = TRUE;
2284 fmt.font = wp_get_font_index(font_name,
2289 if (font_size_set) {
2290 fmt.font_size = wp_get_font_size_index(
2291 font_size, DEFAULT_FONT_SIZE);
2292 fmt.cs.font_size = TRUE;
2294 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2296 gtk_widget_destroy (dialog);
2298 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2302 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2304 ModestMsgEditWindowPrivate *priv;
2306 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2307 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2309 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2311 update_dimmed (window);
2316 update_dimmed (ModestMsgEditWindow *window)
2318 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2319 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2323 gboolean editor_focused;
2325 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2326 editor_focused = gtk_widget_is_focus (priv->msg_body);
2328 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2329 gtk_action_set_sensitive (action, rich_text && editor_focused);
2330 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2331 gtk_action_set_sensitive (action, rich_text && editor_focused);
2332 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2333 gtk_action_set_sensitive (action, rich_text && editor_focused);
2334 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2335 gtk_action_set_sensitive (action, rich_text && editor_focused);
2336 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2337 gtk_action_set_sensitive (action, rich_text && editor_focused);
2338 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2339 gtk_action_set_sensitive (action, rich_text && editor_focused);
2340 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2341 gtk_action_set_sensitive (action, rich_text && editor_focused);
2342 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2343 gtk_action_set_sensitive (action, rich_text && editor_focused);
2344 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2345 gtk_action_set_sensitive (action, rich_text && editor_focused);
2346 widget = priv->font_color_button;
2347 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2348 widget = priv->font_size_toolitem;
2349 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2350 widget = priv->font_face_toolitem;
2351 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2355 setup_insensitive_handlers (ModestMsgEditWindow *window)
2357 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2358 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2361 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2362 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2363 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2364 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2366 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2367 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2368 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2369 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2370 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2371 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2372 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
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/AlignmentMenu/AlignmentCenterMenu");
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/AlignmentRightMenu");
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/AttachmentsMenu/InsertImageMenu");
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, "/ToolBar/ActionsBold");
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, "/ToolBar/ActionsItalics");
2383 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2384 widget = priv->font_color_button;
2385 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2386 widget = priv->font_size_toolitem;
2387 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2388 widget = priv->font_face_toolitem;
2389 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2391 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2392 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (remove_attachment_insensitive_press), window);
2393 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2394 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (zoom_insensitive_press), window);
2396 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2397 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (paste_insensitive_press), window);
2398 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2399 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (copy_insensitive_press), window);
2403 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2405 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2408 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2409 gtk_action_set_sensitive (action, can_undo);
2413 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2416 GtkTextIter match_start, match_end;
2418 if (image_id == NULL)
2421 gtk_text_buffer_get_start_iter (buffer, &iter);
2423 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2424 GSList *tags = gtk_text_iter_get_tags (&match_start);
2426 for (node = tags; node != NULL; node = g_slist_next (node)) {
2427 GtkTextTag *tag = (GtkTextTag *) node->data;
2428 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2429 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2430 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2432 offset = gtk_text_iter_get_offset (&match_start);
2433 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2434 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2438 gtk_text_iter_forward_char (&iter);
2443 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2445 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2446 GtkTextIter real_start, real_end;
2447 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2449 if (gtk_text_iter_compare (start, end) > 0) {
2453 real_start = *start;
2457 GSList *tags = gtk_text_iter_get_tags (&real_start);
2459 for (node = tags; node != NULL; node = g_slist_next (node)) {
2460 GtkTextTag *tag = (GtkTextTag *) node->data;
2461 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2462 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2464 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2466 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2469 } while (gtk_text_iter_forward_char (&real_start)&&
2470 (gtk_text_iter_compare (&real_start, &real_end)<=0));
2474 msg_body_focus (GtkWidget *focus,
2475 GdkEventFocus *event,
2479 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2484 recpt_field_changed (GtkTextBuffer *buffer,
2485 ModestMsgEditWindow *editor)
2487 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2488 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2489 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2490 gboolean dim = FALSE;
2493 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2494 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2495 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2497 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2498 gtk_text_buffer_get_char_count (cc_buffer) +
2499 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2501 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2502 gtk_action_set_sensitive (action, !dim);
2503 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2504 gtk_action_set_sensitive (action, !dim);
2508 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2510 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2514 zoom_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2516 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2520 remove_attachment_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2522 ModestWindowPrivate *parent_priv;
2523 ModestMsgEditWindowPrivate *priv;
2524 GList *selected_attachments = NULL;
2525 gint n_att_selected = 0;
2527 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2528 parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2530 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2531 n_att_selected = g_list_length (selected_attachments);
2532 g_list_free (selected_attachments);
2534 if (n_att_selected > 1)
2535 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unable_to_display_more"));
2536 else if (n_att_selected == 0)
2537 hildon_banner_show_information (NULL, NULL, _("TODO: select one attachment"));
2539 hildon_banner_show_information (NULL, NULL, _("mail_ib_unable_to_purge_attachments"));
2543 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2545 gboolean rich_text, editor_focused;
2547 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2548 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2549 editor_focused = gtk_widget_is_focus (priv->msg_body);
2552 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2553 else if (!editor_focused)
2554 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2558 reset_modified (ModestMsgEditWindow *editor)
2560 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2561 GtkTextBuffer *buffer;
2563 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2564 gtk_text_buffer_set_modified (buffer, FALSE);
2565 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2566 gtk_text_buffer_set_modified (buffer, FALSE);
2567 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2568 gtk_text_buffer_set_modified (buffer, FALSE);
2569 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2573 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2575 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2576 GtkTextBuffer *buffer;
2578 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2579 if (gtk_text_buffer_get_modified (buffer))
2581 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2582 if (gtk_text_buffer_get_modified (buffer))
2584 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2585 if (gtk_text_buffer_get_modified (buffer))
2587 if (gtk_text_buffer_get_modified (priv->text_buffer))
2594 modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
2596 ModestMsgEditWindowPrivate *priv = NULL;
2598 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2599 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2601 /* check if there's no recipient added */
2602 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2603 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2604 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2605 /* no recipient contents, then select contacts */
2606 modest_msg_edit_window_open_addressbook (window, NULL);
2610 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
2612 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
2614 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
2617 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2624 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2625 ModestMsgEditWindow *window)
2627 modest_msg_edit_window_attach_file (window);
2631 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2633 ModestMsgEditWindow *window)
2635 ModestWindowPrivate *parent_priv;
2636 ModestMsgEditWindowPrivate *priv;
2640 GList *selected_attachments = NULL;
2641 gint n_att_selected = 0;
2643 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2644 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2645 selection = gtk_clipboard_wait_for_text (clipboard);
2646 focused = gtk_window_get_focus (GTK_WINDOW (window));
2648 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2649 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2650 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2651 gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2653 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2654 n_att_selected = g_list_length (selected_attachments);
2655 g_list_free (selected_attachments);
2657 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2658 gtk_action_set_sensitive (action, n_att_selected == 1);
2661 update_paste_dimming (window);
2665 update_window_title (ModestMsgEditWindow *window)
2667 ModestMsgEditWindowPrivate *priv = NULL;
2668 const gchar *subject;
2670 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2671 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2672 if (subject == NULL || subject[0] == '\0')
2673 subject = _("mail_va_new_email");
2675 gtk_window_set_title (GTK_WINDOW (window), subject);
2680 subject_field_changed (GtkEditable *editable,
2681 ModestMsgEditWindow *window)
2683 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2684 update_window_title (window);
2685 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2689 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2692 ModestMsgEditWindowPrivate *priv = NULL;
2694 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2695 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2697 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2699 gtk_widget_show_all (priv->find_toolbar);
2700 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2702 gtk_widget_hide_all (priv->find_toolbar);
2703 gtk_widget_grab_focus (priv->msg_body);
2709 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2711 GtkTextIter *match_start,
2712 GtkTextIter *match_end)
2714 GtkTextIter end_iter;
2715 gchar *str_casefold;
2718 gchar *range_casefold;
2721 gboolean result = FALSE;
2728 gtk_text_iter_forward_to_end (&end_iter);
2730 str_casefold = g_utf8_casefold (str, -1);
2731 str_chars_n = strlen (str);
2733 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2734 range_casefold = g_utf8_casefold (range_text, -1);
2735 range_chars_n = strlen (range_casefold);
2737 if (range_chars_n < str_chars_n) {
2738 g_free (str_casefold);
2739 g_free (range_text);
2740 g_free (range_casefold);
2744 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2745 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2746 if (!g_utf8_collate (range_subtext, str_casefold)) {
2747 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2749 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2750 match_start, match_end, NULL);
2751 g_free (found_text);
2753 g_free (range_subtext);
2757 g_free (str_casefold);
2758 g_free (range_text);
2759 g_free (range_casefold);
2766 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2767 ModestMsgEditWindow *window)
2769 gchar *current_search = NULL;
2770 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2772 GtkTextIter selection_start, selection_end;
2773 GtkTextIter match_start, match_end;
2774 gboolean continue_search = FALSE;
2776 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2777 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2778 g_free (current_search);
2779 g_free (priv->last_search);
2780 priv->last_search = NULL;
2781 /* Information banner about empty search */
2782 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2786 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2787 continue_search = TRUE;
2789 g_free (priv->last_search);
2790 priv->last_search = g_strdup (current_search);
2793 if (continue_search) {
2794 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2795 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2796 &match_start, &match_end);
2798 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2800 GtkTextIter buffer_start;
2801 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2802 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2803 &match_start, &match_end);
2805 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2808 /* Mark as selected the string found in search */
2810 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2811 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2813 g_free (priv->last_search);
2814 priv->last_search = NULL;
2816 g_free (current_search);
2820 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2821 ModestMsgEditWindow *window)
2823 GtkToggleAction *toggle;
2824 ModestWindowPrivate *parent_priv;
2825 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2827 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2828 gtk_toggle_action_set_active (toggle, FALSE);
2833 update_paste_dimming (ModestMsgEditWindow *window)
2835 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2836 GtkAction *action = NULL;
2837 GtkClipboard *clipboard = NULL;
2841 focused = gtk_window_get_focus (GTK_WINDOW (window));
2843 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2844 active = gtk_clipboard_wait_is_text_available (clipboard);
2847 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2851 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2852 gtk_action_set_sensitive (action, active);
2857 paste_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2859 GtkWidget *focused = gtk_window_get_focus (GTK_WINDOW (editor));
2861 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2862 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_unable_to_paste_here"));
2864 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ecoc_ib_edwin_nothing_to_paste"));
2869 copy_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2871 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_unable_to_copy"));
2877 modest_msg_edit_window_system_clipboard_owner_change (GtkClipboard *clipboard,
2879 ModestMsgEditWindow *window)
2881 update_paste_dimming (window);
2885 update_select_all_dimming (ModestMsgEditWindow *window)
2888 gboolean dimmed = FALSE;
2890 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2892 focused = gtk_window_get_focus (GTK_WINDOW (window));
2893 if (GTK_IS_ENTRY (focused)) {
2894 const gchar *current_text;
2895 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
2896 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
2897 } else if (GTK_IS_TEXT_VIEW (focused)) {
2898 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
2899 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
2900 } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
2903 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
2904 gtk_action_set_sensitive (action, !dimmed);
2908 update_zoom_dimming (ModestMsgEditWindow *window)
2911 gboolean dimmed = FALSE;
2913 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2915 focused = gtk_window_get_focus (GTK_WINDOW (window));
2916 dimmed = ! WP_IS_TEXT_VIEW (focused);
2917 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2918 gtk_action_set_sensitive (action, !dimmed);
2922 edit_menu_activated (GtkAction *action,
2925 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2927 update_select_all_dimming (window);
2930 view_menu_activated (GtkAction *action,
2933 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2935 update_zoom_dimming (window);
2939 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
2941 ModestMsgEditWindowPrivate *priv;
2943 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
2948 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
2951 ModestMsgEditWindowPrivate *priv;
2953 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);