1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
41 #include <modest-account-mgr.h>
42 #include <modest-account-mgr-helpers.h>
44 #include <widgets/modest-msg-edit-window.h>
45 #include <widgets/modest-combo-box.h>
46 #include <widgets/modest-recpt-editor.h>
47 #include <widgets/modest-attachments-view.h>
49 #include <modest-runtime.h>
51 #include "modest-platform.h"
52 #include "modest-icon-names.h"
53 #include "modest-widget-memory.h"
54 #include "modest-window-priv.h"
55 #include "modest-mail-operation.h"
56 #include "modest-tny-platform-factory.h"
57 #include "modest-tny-msg.h"
58 #include "modest-tny-folder.h"
59 #include "modest-address-book.h"
60 #include "modest-text-utils.h"
61 #include <tny-simple-list.h>
62 #include <wptextview.h>
63 #include <wptextbuffer.h>
64 #include "modest-scroll-area.h"
66 #include "modest-hildon-includes.h"
67 #ifdef MODEST_HAVE_HILDON0_WIDGETS
68 #include <hildon-widgets/hildon-color-chooser.h>
70 #include "widgets/modest-msg-edit-window-ui.h"
71 #ifdef MODEST_HAVE_HILDON0_WIDGETS
72 #include <libgnomevfs/gnome-vfs-mime-utils.h>
74 #include <libgnomevfs/gnome-vfs-mime.h>
76 #include "modest-maemo-utils.h"
79 #define DEFAULT_FONT_SIZE 3
80 #define DEFAULT_FONT 2
81 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
82 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
83 #define DEFAULT_MAIN_VBOX_SPACING 6
84 #define SUBJECT_MAX_LENGTH 1000
85 #define IMAGE_MAX_WIDTH 640
87 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
88 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
89 static void modest_msg_edit_window_finalize (GObject *obj);
91 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
92 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
93 static void send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
94 static void style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
95 static void remove_attachment_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
96 static void zoom_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
97 static void paste_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
98 static void copy_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
99 static void setup_insensitive_handlers (ModestMsgEditWindow *editor);
100 static void reset_modified (ModestMsgEditWindow *editor);
102 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
103 static void text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata);
104 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
105 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
106 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
107 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
108 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
110 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
112 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
114 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
115 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
116 GdkEventWindowState *event,
118 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
119 ModestRecptEditor *editor);
120 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
121 ModestMsgEditWindow *window);
123 /* ModestWindow methods implementation */
124 static void modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom);
125 static gdouble modest_msg_edit_window_get_zoom (ModestWindow *window);
126 static gboolean modest_msg_edit_window_zoom_minus (ModestWindow *window);
127 static gboolean modest_msg_edit_window_zoom_plus (ModestWindow *window);
128 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
129 gboolean show_toolbar);
130 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
132 ModestMsgEditWindow *window);
133 static void modest_msg_edit_window_system_clipboard_owner_change (GtkClipboard *clipboard,
135 ModestMsgEditWindow *window);
136 static void update_window_title (ModestMsgEditWindow *window);
137 static void update_dimmed (ModestMsgEditWindow *window);
138 static void update_paste_dimming (ModestMsgEditWindow *window);
139 static void update_select_all_dimming (ModestMsgEditWindow *window);
140 static void update_zoom_dimming (ModestMsgEditWindow *window);
143 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
144 ModestMsgEditWindow *window);
145 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
146 ModestMsgEditWindow *window);
147 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
149 GtkTextIter *match_start,
150 GtkTextIter *match_end);
154 /* static gboolean */
155 /* on_key_pressed (GtkWidget *self, */
156 /* GdkEventKey *event, */
157 /* gpointer user_data); */
159 static void edit_menu_activated (GtkAction *action,
161 static void view_menu_activated (GtkAction *action,
164 /* list my signals */
171 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
172 struct _ModestMsgEditWindowPrivate {
174 GtkWidget *header_box;
176 ModestPairList *from_field_protos;
177 GtkWidget *from_field;
181 GtkWidget *bcc_field;
182 GtkWidget *subject_field;
183 GtkWidget *attachments_view;
184 GtkWidget *priority_icon;
185 GtkWidget *add_attachment_button;
187 GtkWidget *cc_caption;
188 GtkWidget *bcc_caption;
189 GtkWidget *attachments_caption;
191 GtkTextBuffer *text_buffer;
193 GtkWidget *font_size_toolitem;
194 GtkWidget *font_face_toolitem;
195 GtkWidget *font_color_button;
196 GSList *font_items_group;
197 GtkWidget *font_tool_button_label;
198 GSList *size_items_group;
199 GtkWidget *size_tool_button_label;
201 GtkWidget *find_toolbar;
205 GtkWidget *scroll_area;
210 TnyHeaderFlags priority_flags;
214 gulong clipboard_change_handler_id;
215 gulong system_clipboard_change_handler_id;
221 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
222 MODEST_TYPE_MSG_EDIT_WINDOW, \
223 ModestMsgEditWindowPrivate))
225 static GtkWindowClass *parent_class = NULL;
227 /* uncomment the following if you have defined any signals */
228 /* static guint signals[LAST_SIGNAL] = {0}; */
231 modest_msg_edit_window_get_type (void)
233 static GType my_type = 0;
235 static const GTypeInfo my_info = {
236 sizeof(ModestMsgEditWindowClass),
237 NULL, /* base init */
238 NULL, /* base finalize */
239 (GClassInitFunc) modest_msg_edit_window_class_init,
240 NULL, /* class finalize */
241 NULL, /* class data */
242 sizeof(ModestMsgEditWindow),
244 (GInstanceInitFunc) modest_msg_edit_window_init,
247 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
248 "ModestMsgEditWindow",
251 wp_text_buffer_library_init ();
257 save_state (ModestWindow *self)
259 modest_widget_memory_save (modest_runtime_get_conf(),
260 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
265 restore_settings (ModestMsgEditWindow *self)
267 modest_widget_memory_restore (modest_runtime_get_conf(),
268 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
273 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
275 GObjectClass *gobject_class;
276 ModestWindowClass *modest_window_class;
277 gobject_class = (GObjectClass*) klass;
278 modest_window_class = (ModestWindowClass*) klass;
280 parent_class = g_type_class_peek_parent (klass);
281 gobject_class->finalize = modest_msg_edit_window_finalize;
283 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
284 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
285 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
286 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
287 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
288 modest_window_class->save_state_func = save_state;
290 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
296 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
298 ModestMsgEditWindowPrivate *priv;
299 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
301 priv->msg_body = NULL;
302 priv->from_field = NULL;
303 priv->to_field = NULL;
304 priv->cc_field = NULL;
305 priv->bcc_field = NULL;
306 priv->subject_field = NULL;
307 priv->attachments = NULL;
309 priv->zoom_level = 1.0;
311 priv->cc_caption = NULL;
312 priv->bcc_caption = NULL;
314 priv->priority_flags = 0;
316 priv->find_toolbar = NULL;
317 priv->last_search = NULL;
319 priv->draft_msg = NULL;
320 priv->clipboard_change_handler_id = 0;
321 priv->system_clipboard_change_handler_id = 0;
326 /* FIXME: this is a dup from the one in gtk/ */
329 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
331 static ModestPairList*
332 get_transports (void)
334 GSList *transports = NULL;
336 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
337 GSList *accounts = modest_account_mgr_account_names (account_mgr,
338 TRUE /* only enabled accounts. */);
340 GSList *cursor = accounts;
342 gchar *account_name = cursor->data;
343 gchar *from_string = NULL;
345 from_string = modest_account_mgr_get_from_string (account_mgr,
349 if (from_string && account_name) {
350 gchar *name = account_name;
351 ModestPair *pair = modest_pair_new ((gpointer) name,
352 (gpointer) from_string , TRUE);
353 transports = g_slist_prepend (transports, pair);
356 cursor = cursor->next;
358 g_slist_free (accounts); /* only free the accounts, not the elements,
359 * because they are used in the pairlist */
365 init_window (ModestMsgEditWindow *obj)
367 GtkWidget *from_caption, *to_caption, *subject_caption;
368 GtkWidget *main_vbox;
369 ModestMsgEditWindowPrivate *priv;
371 GtkSizeGroup *size_group;
373 GtkWidget *subject_box;
374 GtkWidget *attachment_icon;
375 GtkWidget *window_box;
377 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
379 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
381 /* Note: This ModestPairList* must exist for as long as the combo
382 * that uses it, because the ModestComboBox uses the ID opaquely,
383 * so it can't know how to manage its memory. */
384 priv->from_field_protos = get_transports ();
386 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
388 priv->to_field = modest_recpt_editor_new ();
389 priv->cc_field = modest_recpt_editor_new ();
390 priv->bcc_field = modest_recpt_editor_new ();
391 subject_box = gtk_hbox_new (FALSE, 0);
392 priv->priority_icon = gtk_image_new ();
393 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
394 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
395 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
396 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
397 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
398 priv->add_attachment_button = gtk_button_new ();
399 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
400 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
401 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
402 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
403 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
404 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
405 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
406 priv->attachments_view = modest_attachments_view_new (NULL);
408 priv->header_box = gtk_vbox_new (FALSE, 0);
410 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
411 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
412 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
413 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
414 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
415 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
416 g_object_unref (size_group);
418 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
419 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
420 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
421 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
422 gtk_size_group_add_widget (size_group, priv->subject_field);
423 gtk_size_group_add_widget (size_group, priv->attachments_view);
424 g_object_unref (size_group);
426 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
427 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
428 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
429 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
430 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
431 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
432 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
435 priv->msg_body = wp_text_view_new ();
436 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
437 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
438 g_object_set (priv->text_buffer, "font_scale", 1.0, NULL);
439 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
440 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
441 gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
443 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
445 priv->find_toolbar = hildon_find_toolbar_new (NULL);
446 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
448 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
450 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
451 G_CALLBACK (text_buffer_refresh_attributes), obj);
452 g_signal_connect (G_OBJECT (priv->text_buffer), "delete-range",
453 G_CALLBACK (text_buffer_delete_range), obj);
454 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
455 G_CALLBACK (text_buffer_can_undo), obj);
456 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
457 G_CALLBACK (text_buffer_can_redo), obj);
458 g_signal_connect (G_OBJECT (obj), "window-state-event",
459 G_CALLBACK (modest_msg_edit_window_window_state_event),
461 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
462 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
463 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
464 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
465 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
466 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
468 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
469 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
471 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
472 G_CALLBACK (msg_body_focus), obj);
473 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
474 G_CALLBACK (msg_body_focus), obj);
475 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
476 "changed", G_CALLBACK (recpt_field_changed), obj);
477 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
478 "changed", G_CALLBACK (recpt_field_changed), obj);
479 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
480 "changed", G_CALLBACK (recpt_field_changed), obj);
481 recpt_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
482 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
484 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
485 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
487 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
488 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
489 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
491 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
493 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
494 frame = gtk_frame_new (NULL);
495 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
497 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
498 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
499 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
501 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL)) {
502 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
503 gtk_widget_hide (priv->cc_caption);
505 if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL)) {
506 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
507 gtk_widget_hide (priv->bcc_caption);
510 window_box = gtk_vbox_new (FALSE, 0);
511 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
512 gtk_box_pack_end (GTK_BOX (window_box), priv->find_toolbar, FALSE, FALSE, 0);
513 gtk_container_add (GTK_CONTAINER(obj), window_box);
514 priv->scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
515 gtk_container_add (GTK_CONTAINER (frame), priv->scroll_area);
518 TODO: scroll_area was never instantiated.
519 Stop building without warnings-as-errors. murrayc.
520 gtk_container_set_focus_vadjustment (GTK_CONTAINER (scroll_area),
521 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
524 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
525 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
526 priv->system_clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
527 G_CALLBACK (modest_msg_edit_window_system_clipboard_owner_change), obj);
533 modest_msg_edit_window_finalize (GObject *obj)
535 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
537 if (priv->clipboard_change_handler_id > 0) {
538 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), priv->clipboard_change_handler_id);
539 priv->clipboard_change_handler_id = 0;
542 if (priv->system_clipboard_change_handler_id > 0) {
543 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
544 priv->system_clipboard_change_handler_id);
545 priv->system_clipboard_change_handler_id = 0;
548 if (priv->draft_msg != NULL) {
549 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
550 if (TNY_IS_HEADER (header)) {
551 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
552 modest_window_mgr_unregister_header (mgr, header);
554 g_object_unref (priv->draft_msg);
555 priv->draft_msg = NULL;
558 /* This had to stay alive for as long as the combobox that used it: */
559 modest_pair_list_free (priv->from_field_protos);
561 G_OBJECT_CLASS(parent_class)->finalize (obj);
565 menubar_to_menu (GtkUIManager *ui_manager)
567 GtkWidget *main_menu;
571 /* Create new main menu */
572 main_menu = gtk_menu_new();
574 /* Get the menubar from the UI manager */
575 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
577 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
581 menu = GTK_WIDGET (iter->data);
582 gtk_widget_reparent(menu, main_menu);
584 iter = g_list_next (iter);
591 set_msg (ModestMsgEditWindow *self, TnyMsg *msg)
594 const gchar *to, *cc, *bcc, *subject;
596 ModestMsgEditWindowPrivate *priv;
598 TnyHeaderFlags priority_flags;
599 TnyFolder *msg_folder;
601 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
602 g_return_if_fail (TNY_IS_MSG (msg));
604 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
606 header = tny_msg_get_header (msg);
607 to = tny_header_get_to (header);
608 cc = tny_header_get_cc (header);
609 bcc = tny_header_get_bcc (header);
610 subject = tny_header_get_subject (header);
611 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
614 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
616 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
617 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
618 gtk_widget_show (priv->cc_caption);
619 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
620 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
621 gtk_widget_hide (priv->cc_caption);
624 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
625 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
626 gtk_widget_show (priv->bcc_caption);
627 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
628 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
629 gtk_widget_hide (priv->bcc_caption);
632 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
633 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
636 update_window_title (self);
638 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
639 body = modest_tny_msg_get_body (msg, TRUE);
641 if ((body == NULL)||(body[0] == '\0')) {
643 body = modest_text_utils_convert_to_html ("");
645 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
646 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
649 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
652 /* Get the default format required from configuration */
653 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
654 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
657 /* Set the default focus depending on having already a To: field or not */
658 if ((!to)||(*to == '\0')) {
659 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
661 gtk_widget_grab_focus (priv->msg_body);
664 /* TODO: lower priority, select in the From: combo to the
665 value that comes from msg <- not sure, should it be
668 /* Add attachments to the view */
669 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
670 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
671 if (priv->attachments == NULL) {
672 gtk_widget_hide (priv->attachments_caption);
674 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
675 gtk_widget_show_all (priv->attachments_caption);
678 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
679 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
681 reset_modified (self);
683 update_dimmed (self);
684 text_buffer_can_undo (priv->text_buffer, FALSE, self);
685 text_buffer_can_redo (priv->text_buffer, FALSE, self);
687 /* we should set a reference to the incoming message if it is a draft */
688 msg_folder = tny_msg_get_folder (msg);
690 if (modest_tny_folder_is_local_folder (msg_folder) &&
691 modest_tny_folder_get_local_folder_type (msg_folder) == TNY_FOLDER_TYPE_DRAFTS)
692 priv->draft_msg = g_object_ref(msg);
693 g_object_unref (msg_folder);
698 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
701 GList *item_children, *node;
702 GtkWidget *bin_child;
704 bin_child = gtk_bin_get_child (GTK_BIN(item));
706 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
708 for (node = item_children; node != NULL; node = g_list_next (node)) {
709 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
710 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
713 g_list_free (item_children);
717 menu_tool_button_dont_expand (GtkMenuToolButton *item)
720 GList *item_children, *node;
722 box = gtk_bin_get_child (GTK_BIN (item));
723 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
724 item_children = gtk_container_get_children (GTK_CONTAINER (box));
726 for (node = item_children; node != NULL; node = g_list_next (node)) {
727 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
728 if (GTK_IS_TOGGLE_BUTTON (node->data))
729 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
730 else if (GTK_IS_BUTTON (node->data))
731 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
733 g_list_free (item_children);
738 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
740 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
741 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
742 GtkWidget *placeholder;
743 GtkWidget *tool_item;
748 GtkWidget *sizes_menu;
749 GtkWidget *fonts_menu;
750 GSList *radio_group = NULL;
755 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
756 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
758 /* should we hide the toolbar? */
759 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
760 gtk_widget_hide (parent_priv->toolbar);
762 /* Font color placeholder */
763 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
764 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
767 tool_item = GTK_WIDGET (gtk_tool_item_new ());
768 priv->font_color_button = hildon_color_button_new ();
769 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
770 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
771 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
772 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
773 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
774 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
775 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
777 /* Font size and face placeholder */
778 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
779 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
781 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
782 priv->size_tool_button_label = gtk_label_new (NULL);
783 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
784 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
785 size_text,"</span>", NULL);
786 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
788 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
789 sizes_menu = gtk_menu_new ();
790 priv->size_items_group = NULL;
792 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
793 GtkWidget *size_menu_item;
795 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
796 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
797 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
798 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
799 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
800 gtk_widget_show (size_menu_item);
802 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
806 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
807 GtkWidget *item = (GtkWidget *) node->data;
808 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
812 priv->size_items_group = g_slist_reverse (priv->size_items_group);
813 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
814 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
815 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
816 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
817 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
818 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
819 priv->font_size_toolitem = tool_item;
822 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
823 priv->font_tool_button_label = gtk_label_new (NULL);
824 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
825 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
827 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
828 fonts_menu = gtk_menu_new ();
829 priv->font_items_group = NULL;
831 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
832 GtkWidget *font_menu_item;
833 GtkWidget *child_label;
835 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
836 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
837 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
838 wp_get_font_name (font_index), "</span>", NULL);
839 gtk_label_set_markup (GTK_LABEL (child_label), markup);
842 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
843 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
844 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
845 gtk_widget_show (font_menu_item);
847 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
850 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
851 GtkWidget *item = (GtkWidget *) node->data;
852 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
855 priv->font_items_group = g_slist_reverse (priv->font_items_group);
856 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
857 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
858 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
859 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
860 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
861 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
862 priv->font_face_toolitem = tool_item;
864 /* Set expand and homogeneous for remaining items */
865 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
866 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
867 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
868 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
869 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
870 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
871 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
872 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
873 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
881 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name)
884 ModestWindowPrivate *parent_priv;
885 ModestMsgEditWindowPrivate *priv;
886 GtkActionGroup *action_group;
887 GError *error = NULL;
888 GdkPixbuf *window_icon = NULL;
891 gboolean prefer_formatted;
893 ModestPair *account_pair = NULL;
895 g_return_val_if_fail (msg, NULL);
896 g_return_val_if_fail (account_name, NULL);
898 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
900 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
901 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
903 parent_priv->ui_manager = gtk_ui_manager_new();
904 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
905 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
907 /* Add common actions */
908 gtk_action_group_add_actions (action_group,
909 modest_msg_edit_action_entries,
910 G_N_ELEMENTS (modest_msg_edit_action_entries),
912 gtk_action_group_add_toggle_actions (action_group,
913 modest_msg_edit_toggle_action_entries,
914 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
916 gtk_action_group_add_radio_actions (action_group,
917 modest_msg_edit_alignment_radio_action_entries,
918 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
920 G_CALLBACK (modest_ui_actions_on_change_justify),
922 gtk_action_group_add_radio_actions (action_group,
923 modest_msg_edit_zoom_action_entries,
924 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
926 G_CALLBACK (modest_ui_actions_on_change_zoom),
928 gtk_action_group_add_radio_actions (action_group,
929 modest_msg_edit_priority_action_entries,
930 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
932 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
934 gtk_action_group_add_radio_actions (action_group,
935 modest_msg_edit_file_format_action_entries,
936 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
937 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
938 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
940 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
941 g_object_unref (action_group);
943 /* Load the UI definition */
944 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
947 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
948 g_clear_error (&error);
951 /* Add accelerators */
952 gtk_window_add_accel_group (GTK_WINDOW (obj),
953 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
956 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
957 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
960 init_window (MODEST_MSG_EDIT_WINDOW(obj));
962 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
964 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
966 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
968 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
970 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
971 if (account_pair != NULL)
972 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
974 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg);
976 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
978 /* Set window icon */
979 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
980 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
982 /* Dim at start clipboard actions */
983 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
984 gtk_action_set_sensitive (action, FALSE);
985 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
986 gtk_action_set_sensitive (action, FALSE);
987 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
988 gtk_action_set_sensitive (action, FALSE);
990 /* Update select all */
991 update_select_all_dimming (MODEST_MSG_EDIT_WINDOW (obj));
992 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu");
993 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (edit_menu_activated), obj);
994 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu");
995 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (view_menu_activated), obj);
997 /* set initial state of cc and bcc */
998 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
999 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1000 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
1001 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
1002 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1003 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
1005 /* Setup the file format */
1006 conf = modest_runtime_get_conf ();
1007 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
1009 g_clear_error (&error);
1010 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
1012 file_format = (prefer_formatted) ?
1013 MODEST_FILE_FORMAT_FORMATTED_TEXT :
1014 MODEST_FILE_FORMAT_PLAIN_TEXT;
1015 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
1017 update_paste_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1019 return (ModestWindow*) obj;
1023 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1025 GString **string_buffer = (GString **) user_data;
1027 *string_buffer = g_string_append (*string_buffer, buffer);
1033 * @result: A new string which should be freed with g_free().
1036 get_formatted_data (ModestMsgEditWindow *edit_window)
1038 ModestMsgEditWindowPrivate *priv;
1039 GString *string_buffer = g_string_new ("");
1041 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1043 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1045 return g_string_free (string_buffer, FALSE);
1050 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1053 const gchar *account_name;
1054 ModestMsgEditWindowPrivate *priv;
1056 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1058 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1060 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1061 g_return_val_if_fail (account_name, NULL);
1064 /* don't free these (except from) */
1065 data = g_slice_new0 (MsgData);
1066 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1068 data->account_name = g_strdup (account_name);
1069 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1070 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1071 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1072 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1073 if (priv->draft_msg) {
1074 data->draft_msg = g_object_ref (priv->draft_msg);
1076 data->draft_msg = NULL;
1079 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1081 gtk_text_buffer_get_bounds (buf, &b, &e);
1082 data->plain_body = g_strdup (gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE)); /* returns a copy */
1084 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1085 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1087 data->html_body = NULL;
1089 /* deep-copy the data */
1090 GList *cursor = priv->attachments;
1091 data->attachments = NULL;
1093 if (!(TNY_IS_MIME_PART(cursor->data))) {
1094 g_warning ("strange data in attachment list");
1097 data->attachments = g_list_append (data->attachments,
1098 g_object_ref (cursor->data));
1099 cursor = g_list_next (cursor);
1102 data->priority_flags = priv->priority_flags;
1109 unref_gobject (GObject *obj, gpointer data)
1111 if (!G_IS_OBJECT(obj))
1113 g_object_unref (obj);
1117 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1120 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1128 g_free (data->subject);
1129 g_free (data->plain_body);
1130 g_free (data->html_body);
1131 g_free (data->account_name);
1133 if (data->draft_msg != NULL) {
1134 g_object_unref (data->draft_msg);
1135 data->draft_msg = NULL;
1138 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1139 g_list_free (data->attachments);
1141 g_slice_free (MsgData, data);
1145 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1148 ModestMsgEditWindowPrivate *priv = NULL;
1149 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1151 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1153 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1155 return MODEST_MSG_EDIT_FORMAT_HTML;
1157 return MODEST_MSG_EDIT_FORMAT_TEXT;
1161 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1162 ModestMsgEditFormat format)
1164 ModestMsgEditWindowPrivate *priv;
1166 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1167 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1170 case MODEST_MSG_EDIT_FORMAT_HTML:
1171 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1173 case MODEST_MSG_EDIT_FORMAT_TEXT:
1174 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1177 g_return_if_reached ();
1181 ModestMsgEditFormatState *
1182 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1184 ModestMsgEditFormatState *format_state = NULL;
1185 ModestMsgEditWindowPrivate *priv;
1186 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1188 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1189 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1191 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1193 format_state = g_new0 (ModestMsgEditFormatState, 1);
1194 format_state->bold = buffer_format->bold&0x1;
1195 format_state->italics = buffer_format->italic&0x1;
1196 format_state->bullet = buffer_format->bullet&0x1;
1197 format_state->color = buffer_format->color;
1198 format_state->font_size = buffer_format->font_size;
1199 format_state->font_family = wp_get_font_name (buffer_format->font);
1200 format_state->justification = buffer_format->justification;
1201 g_free (buffer_format);
1203 return format_state;
1208 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1209 const ModestMsgEditFormatState *format_state)
1211 ModestMsgEditWindowPrivate *priv;
1212 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1213 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1214 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1215 g_return_if_fail (format_state != NULL);
1217 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1218 gtk_widget_grab_focus (priv->msg_body);
1219 buffer_format->bold = (format_state->bold != FALSE);
1220 buffer_format->italic = (format_state->italics != FALSE);
1221 buffer_format->color = format_state->color;
1222 buffer_format->font_size = format_state->font_size;
1223 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1224 buffer_format->justification = format_state->justification;
1225 buffer_format->bullet = format_state->bullet;
1227 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1229 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1230 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1231 buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
1232 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1233 buffer_format->cs.font = (buffer_format->font != current_format->font);
1234 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1235 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1237 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1238 if (buffer_format->cs.bold) {
1239 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1241 if (buffer_format->cs.italic) {
1242 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1244 if (buffer_format->cs.color) {
1245 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1247 if (buffer_format->cs.font_size) {
1248 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1250 if (buffer_format->cs.justification) {
1251 switch (buffer_format->justification) {
1252 case GTK_JUSTIFY_LEFT:
1253 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1255 case GTK_JUSTIFY_CENTER:
1256 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1258 case GTK_JUSTIFY_RIGHT:
1259 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1266 if (buffer_format->cs.font) {
1267 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1269 if (buffer_format->cs.bullet) {
1270 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((int)buffer_format->bullet));
1272 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1273 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1275 g_free (current_format);
1280 toggle_action_set_active_block_notify (GtkToggleAction *action,
1283 GSList *proxies = NULL;
1285 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1286 proxies != NULL; proxies = g_slist_next (proxies)) {
1287 GtkWidget *widget = (GtkWidget *) proxies->data;
1288 gtk_action_block_activate_from (GTK_ACTION (action), widget);
1291 gtk_toggle_action_set_active (action, value);
1293 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1294 proxies != NULL; proxies = g_slist_next (proxies)) {
1295 GtkWidget *widget = (GtkWidget *) proxies->data;
1296 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
1301 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1303 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1305 ModestWindowPrivate *parent_priv;
1306 ModestMsgEditWindowPrivate *priv;
1307 GtkWidget *new_size_menuitem;
1308 GtkWidget *new_font_menuitem;
1310 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1311 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1313 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1314 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1315 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1316 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1318 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1319 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1320 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1323 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1325 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1326 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1328 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1329 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1331 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1332 toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1334 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1335 G_CALLBACK (modest_msg_edit_window_color_button_change),
1337 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1338 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1339 G_CALLBACK (modest_msg_edit_window_color_button_change),
1342 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1343 buffer_format->font_size))->data);
1344 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1348 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1349 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1350 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1352 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1353 G_CALLBACK (modest_msg_edit_window_size_change),
1355 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1356 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1357 G_CALLBACK (modest_msg_edit_window_size_change),
1361 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1362 buffer_format->font))->data);
1363 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1367 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1368 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1369 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1371 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1372 G_CALLBACK (modest_msg_edit_window_font_change),
1374 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1375 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1376 G_CALLBACK (modest_msg_edit_window_font_change),
1380 g_free (buffer_format);
1386 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1389 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1390 ModestMsgEditWindowPrivate *priv;
1391 GtkWidget *dialog = NULL;
1393 const GdkColor *new_color = NULL;
1395 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1396 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1398 #ifdef MODEST_HILDON_VERSION_0
1399 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1400 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1402 dialog = hildon_color_chooser_new ();
1403 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1404 #endif /*MODEST_HILDON_VERSION_0*/
1405 g_free (buffer_format);
1407 response = gtk_dialog_run (GTK_DIALOG (dialog));
1409 case GTK_RESPONSE_OK: {
1410 #ifdef MODEST_HILDON_VERSION_0
1411 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1414 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1416 #endif /*MODEST_HILDON_VERSION_0*/
1423 gtk_widget_destroy (dialog);
1425 if (new_color != NULL)
1426 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1431 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1434 ModestMsgEditWindowPrivate *priv;
1435 GtkWidget *dialog = NULL;
1437 GdkColor *old_color = NULL;
1438 const GdkColor *new_color = NULL;
1440 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1441 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1443 #ifdef MODEST_HILDON_VERSION_0
1444 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1445 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1447 dialog = hildon_color_chooser_new ();
1448 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1449 #endif /*MODEST_HILDON_VERSION_9*/
1451 response = gtk_dialog_run (GTK_DIALOG (dialog));
1453 case GTK_RESPONSE_OK: {
1454 #ifdef MODEST_HILDON_VERSION_0
1455 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1458 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1460 #endif /*MODEST_HILDON_VERSION_0*/
1466 gtk_widget_destroy (dialog);
1468 if (new_color != NULL)
1469 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1475 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1478 ModestMsgEditWindowPrivate *priv;
1479 GtkWidget *dialog = NULL;
1481 GSList *uris = NULL;
1482 GSList *uri_node = NULL;
1484 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1486 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1487 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1488 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1490 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1492 response = gtk_dialog_run (GTK_DIALOG (dialog));
1494 case GTK_RESPONSE_OK:
1495 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1500 gtk_widget_destroy (dialog);
1502 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1504 GnomeVFSHandle *handle = NULL;
1505 GnomeVFSResult result;
1506 GtkTextIter position;
1507 GtkTextMark *insert_mark;
1509 uri = (const gchar *) uri_node->data;
1510 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1511 if (result == GNOME_VFS_OK) {
1512 GdkPixbufLoader *loader;
1514 GnomeVFSFileInfo info;
1515 gchar *filename, *basename;
1516 TnyMimePart *mime_part;
1519 const gchar *mime_type = NULL;
1521 filename = g_filename_from_uri (uri, NULL, NULL);
1522 if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
1524 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1526 mime_part = tny_platform_factory_new_mime_part
1527 (modest_runtime_get_platform_factory ());
1528 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1530 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1532 content_id = g_strdup_printf ("%d", priv->last_cid);
1533 tny_mime_part_set_content_id (mime_part, content_id);
1534 g_free (content_id);
1537 basename = g_path_get_basename (filename);
1538 tny_mime_part_set_filename (mime_part, basename);
1541 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1542 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1544 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1545 gtk_widget_show_all (priv->attachments_caption);
1546 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1549 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1550 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1551 unsigned char read_buffer[128];
1553 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1554 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
1557 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1558 g_object_ref (pixbuf);
1559 gdk_pixbuf_loader_close (loader, NULL);
1560 g_object_unref (loader);
1562 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1563 GdkPixbuf *new_pixbuf;
1565 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1566 gdk_pixbuf_get_width (pixbuf);
1567 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1568 g_object_unref (pixbuf);
1569 pixbuf = new_pixbuf;
1572 if (pixbuf != NULL) {
1573 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1574 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1575 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1584 modest_msg_edit_window_attach_file (ModestMsgEditWindow *window)
1587 ModestMsgEditWindowPrivate *priv;
1588 GtkWidget *dialog = NULL;
1590 GSList *uris = NULL;
1593 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1595 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1596 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1598 response = gtk_dialog_run (GTK_DIALOG (dialog));
1600 case GTK_RESPONSE_OK:
1601 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1606 gtk_widget_destroy (dialog);
1608 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1610 GnomeVFSHandle *handle = NULL;
1611 GnomeVFSResult result;
1613 uri = (const gchar *) uri_node->data;
1614 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1615 if (result == GNOME_VFS_OK) {
1616 TnyMimePart *mime_part;
1618 const gchar *mime_type = NULL;
1622 GnomeVFSFileInfo info;
1624 filename = g_filename_from_uri (uri, NULL, NULL);
1626 if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE) == GNOME_VFS_OK)
1627 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1628 mime_part = tny_platform_factory_new_mime_part
1629 (modest_runtime_get_platform_factory ());
1630 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1632 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1634 content_id = g_strdup_printf ("%d", priv->last_cid);
1635 tny_mime_part_set_content_id (mime_part, content_id);
1636 g_free (content_id);
1639 basename = g_path_get_basename (filename);
1640 tny_mime_part_set_filename (mime_part, basename);
1643 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1644 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1646 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1647 gtk_widget_show_all (priv->attachments_caption);
1648 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1653 g_slist_foreach (uris, (GFunc) g_free, NULL);
1654 g_slist_free (uris);
1658 modest_msg_edit_window_attach_file_noninteractive (
1659 ModestMsgEditWindow *window,
1660 const gchar *file_uri)
1663 ModestMsgEditWindowPrivate *priv;
1665 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1667 if (file_uri && strlen(file_uri)) {
1670 /* TODO: We should probably try to use only the URI,
1671 * instead of using a filename.
1673 gchar* filename = g_filename_from_uri (file_uri, NULL, NULL);
1675 g_warning("%s: g_filename_from_uri('%s') failed.\n", __FUNCTION__, file_uri);
1678 file_id = g_open (filename, O_RDONLY, 0);
1679 if (file_id != -1) {
1680 TnyMimePart *mime_part;
1682 const gchar *mime_type;
1685 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1686 mime_type = gnome_vfs_get_mime_type(filename);
1688 mime_type = gnome_vfs_get_file_mime_type_fast (filename, NULL);
1690 mime_part = tny_platform_factory_new_mime_part
1691 (modest_runtime_get_platform_factory ());
1692 stream = TNY_STREAM (tny_fs_stream_new (file_id));
1694 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1696 content_id = g_strdup_printf ("%d", priv->last_cid);
1697 tny_mime_part_set_content_id (mime_part, content_id);
1698 g_free (content_id);
1701 basename = g_path_get_basename (filename);
1702 tny_mime_part_set_filename (mime_part, basename);
1705 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1706 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1708 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1709 gtk_widget_show_all (priv->attachments_caption);
1710 } else if (file_id == -1) {
1712 g_warning("file to be attached does not exist: %s", filename);
1720 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1723 ModestMsgEditWindowPrivate *priv;
1724 gboolean clean_list = FALSE;
1726 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1727 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1729 if (att_list == NULL) {
1730 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1734 if (att_list == NULL) {
1735 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1737 GtkWidget *confirmation_dialog = NULL;
1738 gboolean dialog_response;
1740 gchar *message = NULL;
1741 const gchar *filename = NULL;
1743 if (att_list->next == NULL) {
1744 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1748 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1749 att_list->next == NULL), filename);
1750 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1752 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1753 gtk_widget_destroy (confirmation_dialog);
1754 if (!dialog_response) {
1756 g_list_free (att_list);
1759 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1761 for (node = att_list; node != NULL; node = g_list_next (node)) {
1762 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1763 const gchar *att_id;
1764 priv->attachments = g_list_remove (priv->attachments, mime_part);
1766 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1768 if (priv->attachments == NULL)
1769 gtk_widget_hide (priv->attachments_caption);
1770 att_id = tny_mime_part_get_content_id (mime_part);
1772 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1774 g_object_unref (mime_part);
1775 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1780 g_list_free (att_list);
1784 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1787 ModestMsgEditWindowPrivate *priv;
1788 GdkColor *new_color;
1789 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1791 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1792 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1795 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1797 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1799 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1801 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1806 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1809 ModestMsgEditWindowPrivate *priv;
1810 gint new_size_index;
1811 ModestMsgEditWindow *window;
1814 window = MODEST_MSG_EDIT_WINDOW (userdata);
1815 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1816 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1818 if (gtk_check_menu_item_get_active (menu_item)) {
1820 WPTextBufferFormat format;
1822 memset (&format, 0, sizeof (format));
1823 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1825 label = gtk_bin_get_child (GTK_BIN (menu_item));
1827 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1828 format.cs.font_size = TRUE;
1829 format.cs.text_position = TRUE;
1830 format.cs.font = TRUE;
1831 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1832 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1834 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1835 (gpointer) wp_get_font_size_index (new_size_index, 12)))
1836 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1838 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1839 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1840 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1846 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1849 ModestMsgEditWindowPrivate *priv;
1850 gint new_font_index;
1851 ModestMsgEditWindow *window;
1854 window = MODEST_MSG_EDIT_WINDOW (userdata);
1855 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1856 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1858 if (gtk_check_menu_item_get_active (menu_item)) {
1861 label = gtk_bin_get_child (GTK_BIN (menu_item));
1863 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1865 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1866 (gpointer) new_font_index))
1867 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1869 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1870 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1871 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1877 modest_msg_edit_window_set_zoom (ModestWindow *window,
1880 ModestMsgEditWindowPrivate *priv;
1881 ModestWindowPrivate *parent_priv;
1882 GtkRadioAction *zoom_radio_action;
1884 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1886 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1887 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1888 priv->zoom_level = zoom;
1889 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom);
1891 /* Zoom level menu options should be updated with the current zoom level */
1892 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1893 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1894 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1895 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1896 /* FIXME: Not availible before Gtk 2.10 */
1898 gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
1903 modest_msg_edit_window_get_zoom (ModestWindow *window)
1905 ModestMsgEditWindowPrivate *priv;
1907 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1909 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1910 return priv->zoom_level;
1914 zoom_allowed (ModestMsgEditWindow *window)
1918 focus = gtk_window_get_focus (GTK_WINDOW (window));
1919 return (focus != NULL && WP_IS_TEXT_VIEW (focus));
1923 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1925 ModestWindowPrivate *parent_priv;
1926 GtkRadioAction *zoom_radio_action;
1927 GSList *group, *node;
1929 /* First we check if the text view is focused. If not, zooming is not allowed */
1930 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1931 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1935 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1936 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1937 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1939 group = gtk_radio_action_get_group (zoom_radio_action);
1941 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1942 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
1946 for (node = group; node != NULL; node = g_slist_next (node)) {
1947 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1948 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1956 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1958 ModestWindowPrivate *parent_priv;
1959 GtkRadioAction *zoom_radio_action;
1960 GSList *group, *node;
1962 /* First we check if the text view is focused. If not, zooming is not allowed */
1963 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1964 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1968 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1969 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
1970 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1972 group = gtk_radio_action_get_group (zoom_radio_action);
1974 for (node = group; node != NULL; node = g_slist_next (node)) {
1975 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1976 if (node->next != NULL) {
1977 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1980 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
1988 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1990 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1991 ModestWindowPrivate *parent_priv;
1992 ModestWindowMgr *mgr;
1993 gboolean is_fullscreen;
1994 GtkAction *fs_toggle_action;
1997 mgr = modest_runtime_get_window_mgr ();
1998 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2000 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2002 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2003 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2004 if (is_fullscreen != active)
2005 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2013 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
2015 ModestWindowPrivate *parent_priv;
2016 GtkAction *fs_toggle_action;
2019 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2021 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2022 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
2023 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
2027 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2030 ModestMsgEditWindowPrivate *priv = NULL;
2031 const gchar *recipients;
2032 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2034 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2035 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2036 recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field));
2037 if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2038 gtk_widget_show (priv->cc_caption);
2040 gtk_widget_hide (priv->cc_caption);
2041 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2045 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2048 ModestMsgEditWindowPrivate *priv = NULL;
2049 const gchar *recipients;
2050 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2052 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2053 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2054 recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field));
2055 if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2056 gtk_widget_show (priv->bcc_caption);
2058 gtk_widget_hide (priv->bcc_caption);
2059 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2063 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2064 ModestRecptEditor *editor)
2066 ModestMsgEditWindowPrivate *priv;
2068 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2069 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2070 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2072 if (editor == NULL) {
2073 GtkWidget *view_focus;
2074 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2076 /* This code should be kept in sync with ModestRecptEditor. The
2077 textview inside the recpt editor is the one that really gets the
2078 focus. As it's inside a scrolled window, and this one inside the
2079 hbox recpt editor inherits from, we'll need to go up in the
2080 hierarchy to know if the text view is part of the recpt editor
2081 or if it's a different text entry */
2083 if (gtk_widget_get_parent (view_focus)) {
2084 GtkWidget *first_parent;
2086 first_parent = gtk_widget_get_parent (view_focus);
2087 if (gtk_widget_get_parent (first_parent) &&
2088 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2089 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2094 editor = MODEST_RECPT_EDITOR (priv->to_field);
2098 modest_address_book_select_addresses (editor);
2103 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2105 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2107 modest_msg_edit_window_open_addressbook (window, NULL);
2111 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2112 gboolean show_toolbar)
2114 ModestWindowPrivate *parent_priv;
2116 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2117 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2119 /* FIXME: we can not just use the code of
2120 modest_msg_edit_window_setup_toolbar because it has a
2121 mixture of both initialization and creation code. */
2124 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2126 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2130 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2131 TnyHeaderFlags priority_flags)
2133 ModestMsgEditWindowPrivate *priv;
2134 ModestWindowPrivate *parent_priv;
2136 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2138 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2139 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2140 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2142 if (priv->priority_flags != priority_flags) {
2143 GtkAction *priority_action = NULL;
2145 priv->priority_flags = priority_flags;
2147 switch (priority_flags) {
2148 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2149 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2150 gtk_widget_show (priv->priority_icon);
2151 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2152 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2154 case TNY_HEADER_FLAG_LOW_PRIORITY:
2155 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2156 gtk_widget_show (priv->priority_icon);
2157 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2158 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2161 gtk_widget_hide (priv->priority_icon);
2162 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2163 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2166 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2167 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2172 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2175 ModestMsgEditWindowPrivate *priv;
2176 ModestWindowPrivate *parent_priv;
2177 gint current_format;
2179 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2181 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2182 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2184 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2185 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2187 if (current_format != file_format) {
2188 switch (file_format) {
2189 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2190 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2192 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2196 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2197 response = gtk_dialog_run (GTK_DIALOG (dialog));
2198 gtk_widget_destroy (dialog);
2199 if (response == GTK_RESPONSE_OK) {
2200 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2202 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2203 toggle_action_set_active_block_notify (action, TRUE);
2208 update_dimmed (window);
2213 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2216 ModestMsgEditWindowPrivate *priv;
2217 WPTextBufferFormat oldfmt, fmt;
2218 gint old_position = 0;
2222 GdkColor *color = NULL;
2223 gboolean bold, bold_set, italic, italic_set;
2224 gboolean underline, underline_set;
2225 gboolean strikethrough, strikethrough_set;
2226 gboolean position_set;
2227 gboolean font_size_set, font_set, color_set;
2230 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2231 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2233 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2235 /* First we get the currently selected font information */
2236 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2237 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2239 switch (oldfmt.text_position) {
2240 case TEXT_POSITION_NORMAL:
2243 case TEXT_POSITION_SUPERSCRIPT:
2251 g_object_set (G_OBJECT (dialog),
2252 "bold", oldfmt.bold != FALSE,
2253 "bold-set", !oldfmt.cs.bold,
2254 "underline", oldfmt.underline != FALSE,
2255 "underline-set", !oldfmt.cs.underline,
2256 "italic", oldfmt.italic != FALSE,
2257 "italic-set", !oldfmt.cs.italic,
2258 "strikethrough", oldfmt.strikethrough != FALSE,
2259 "strikethrough-set", !oldfmt.cs.strikethrough,
2260 "color", &oldfmt.color,
2261 "color-set", !oldfmt.cs.color,
2262 "size", wp_font_size[oldfmt.font_size],
2263 "size-set", !oldfmt.cs.font_size,
2264 "position", old_position,
2265 "position-set", !oldfmt.cs.text_position,
2266 "family", wp_get_font_name (oldfmt.font),
2267 "family-set", !oldfmt.cs.font,
2270 gtk_widget_show_all (dialog);
2271 response = gtk_dialog_run (GTK_DIALOG (dialog));
2272 if (response == GTK_RESPONSE_OK) {
2274 g_object_get( dialog,
2276 "bold-set", &bold_set,
2277 "underline", &underline,
2278 "underline-set", &underline_set,
2280 "italic-set", &italic_set,
2281 "strikethrough", &strikethrough,
2282 "strikethrough-set", &strikethrough_set,
2284 "color-set", &color_set,
2286 "size-set", &font_size_set,
2287 "family", &font_name,
2288 "family-set", &font_set,
2289 "position", &position,
2290 "position-set", &position_set,
2295 if (response == GTK_RESPONSE_OK) {
2296 memset(&fmt, 0, sizeof(fmt));
2302 fmt.italic = italic;
2303 fmt.cs.italic = TRUE;
2305 if (underline_set) {
2306 fmt.underline = underline;
2307 fmt.cs.underline = TRUE;
2309 if (strikethrough_set) {
2310 fmt.strikethrough = strikethrough;
2311 fmt.cs.strikethrough = TRUE;
2316 ? TEXT_POSITION_NORMAL
2317 : ( ( position == 1 )
2318 ? TEXT_POSITION_SUPERSCRIPT
2319 : TEXT_POSITION_SUBSCRIPT );
2320 fmt.cs.text_position = TRUE;
2324 fmt.cs.color = TRUE;
2327 fmt.font = wp_get_font_index(font_name,
2332 if (font_size_set) {
2333 fmt.font_size = wp_get_font_size_index(
2334 font_size, DEFAULT_FONT_SIZE);
2335 fmt.cs.font_size = TRUE;
2337 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2339 gtk_widget_destroy (dialog);
2341 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2345 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2347 ModestMsgEditWindowPrivate *priv;
2349 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2350 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2352 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2354 update_dimmed (window);
2359 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2361 ModestMsgEditWindowPrivate *priv;
2363 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2364 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2366 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2368 update_dimmed (window);
2373 update_dimmed (ModestMsgEditWindow *window)
2375 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2376 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2380 gboolean editor_focused;
2382 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2383 editor_focused = gtk_widget_is_focus (priv->msg_body);
2385 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2386 gtk_action_set_sensitive (action, rich_text && editor_focused);
2387 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2388 gtk_action_set_sensitive (action, rich_text && editor_focused);
2389 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2390 gtk_action_set_sensitive (action, rich_text && editor_focused);
2391 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2392 gtk_action_set_sensitive (action, rich_text && editor_focused);
2393 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2394 gtk_action_set_sensitive (action, rich_text && editor_focused);
2395 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2396 gtk_action_set_sensitive (action, rich_text && editor_focused);
2397 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2398 gtk_action_set_sensitive (action, rich_text && editor_focused);
2399 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2400 gtk_action_set_sensitive (action, rich_text && editor_focused);
2401 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2402 gtk_action_set_sensitive (action, rich_text && editor_focused);
2403 widget = priv->font_color_button;
2404 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2405 widget = priv->font_size_toolitem;
2406 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2407 widget = priv->font_face_toolitem;
2408 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2412 setup_insensitive_handlers (ModestMsgEditWindow *window)
2414 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2415 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2418 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2419 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2420 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2421 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2423 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2424 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2425 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2426 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2427 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2428 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2429 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2430 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2431 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2432 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2433 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2434 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2435 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2436 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2437 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2438 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2439 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2440 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2441 widget = priv->font_color_button;
2442 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2443 widget = priv->font_size_toolitem;
2444 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2445 widget = priv->font_face_toolitem;
2446 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2448 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2449 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (remove_attachment_insensitive_press), window);
2450 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2451 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (zoom_insensitive_press), window);
2453 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2454 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (paste_insensitive_press), window);
2455 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2456 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (copy_insensitive_press), window);
2460 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2462 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2465 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2466 gtk_action_set_sensitive (action, can_undo);
2470 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2472 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2475 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/RedoMenu");
2476 gtk_action_set_sensitive (action, can_redo);
2480 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2483 GtkTextIter match_start, match_end;
2485 if (image_id == NULL)
2488 gtk_text_buffer_get_start_iter (buffer, &iter);
2490 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2491 GSList *tags = gtk_text_iter_get_tags (&match_start);
2493 for (node = tags; node != NULL; node = g_slist_next (node)) {
2494 GtkTextTag *tag = (GtkTextTag *) node->data;
2495 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2496 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2497 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2499 offset = gtk_text_iter_get_offset (&match_start);
2500 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2501 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2505 gtk_text_iter_forward_char (&iter);
2510 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2512 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2513 GtkTextIter real_start, real_end;
2514 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2516 if (gtk_text_iter_compare (start, end) > 0) {
2520 real_start = *start;
2524 GSList *tags = gtk_text_iter_get_tags (&real_start);
2526 for (node = tags; node != NULL; node = g_slist_next (node)) {
2527 GtkTextTag *tag = (GtkTextTag *) node->data;
2528 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2529 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2531 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2533 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2536 } while (gtk_text_iter_forward_char (&real_start)&&
2537 (gtk_text_iter_compare (&real_start, &real_end)<=0));
2541 msg_body_focus (GtkWidget *focus,
2542 GdkEventFocus *event,
2546 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2551 recpt_field_changed (GtkTextBuffer *buffer,
2552 ModestMsgEditWindow *editor)
2554 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2555 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2556 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2557 gboolean dim = FALSE;
2560 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2561 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2562 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2564 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2565 gtk_text_buffer_get_char_count (cc_buffer) +
2566 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2568 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2569 gtk_action_set_sensitive (action, !dim);
2570 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2571 gtk_action_set_sensitive (action, !dim);
2575 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2577 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2581 zoom_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2583 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2587 remove_attachment_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2589 ModestWindowPrivate *parent_priv;
2590 ModestMsgEditWindowPrivate *priv;
2591 GList *selected_attachments = NULL;
2592 gint n_att_selected = 0;
2594 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2595 parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2597 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2598 n_att_selected = g_list_length (selected_attachments);
2599 g_list_free (selected_attachments);
2601 if (n_att_selected > 1)
2602 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unable_to_display_more"));
2603 else if (n_att_selected == 0)
2604 hildon_banner_show_information (NULL, NULL, _("TODO: select one attachment"));
2606 hildon_banner_show_information (NULL, NULL, _("mail_ib_unable_to_purge_attachments"));
2610 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2612 gboolean rich_text, editor_focused;
2614 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2615 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2616 editor_focused = gtk_widget_is_focus (priv->msg_body);
2619 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2620 else if (!editor_focused)
2621 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2625 reset_modified (ModestMsgEditWindow *editor)
2627 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2628 GtkTextBuffer *buffer;
2630 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2631 gtk_text_buffer_set_modified (buffer, FALSE);
2632 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2633 gtk_text_buffer_set_modified (buffer, FALSE);
2634 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2635 gtk_text_buffer_set_modified (buffer, FALSE);
2636 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2640 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2642 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2643 GtkTextBuffer *buffer;
2645 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2646 if (gtk_text_buffer_get_modified (buffer))
2648 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2649 if (gtk_text_buffer_get_modified (buffer))
2651 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2652 if (gtk_text_buffer_get_modified (buffer))
2654 if (gtk_text_buffer_get_modified (priv->text_buffer))
2661 modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
2663 ModestMsgEditWindowPrivate *priv = NULL;
2665 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2666 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2668 /* check if there's no recipient added */
2669 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2670 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2671 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2672 /* no recipient contents, then select contacts */
2673 modest_msg_edit_window_open_addressbook (window, NULL);
2677 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
2679 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
2681 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
2684 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2691 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2692 ModestMsgEditWindow *window)
2694 modest_msg_edit_window_attach_file (window);
2698 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2700 ModestMsgEditWindow *window)
2702 ModestWindowPrivate *parent_priv;
2703 ModestMsgEditWindowPrivate *priv;
2705 gboolean has_selection;
2707 GList *selected_attachments = NULL;
2708 gint n_att_selected = 0;
2710 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2711 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2712 has_selection = gtk_clipboard_wait_for_targets (clipboard, NULL, NULL);
2713 focused = gtk_window_get_focus (GTK_WINDOW (window));
2715 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2716 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2717 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2718 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2720 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2721 n_att_selected = g_list_length (selected_attachments);
2722 g_list_free (selected_attachments);
2724 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2725 gtk_action_set_sensitive (action, n_att_selected == 1);
2727 update_paste_dimming (window);
2731 update_window_title (ModestMsgEditWindow *window)
2733 ModestMsgEditWindowPrivate *priv = NULL;
2734 const gchar *subject;
2736 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2737 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2738 if (subject == NULL || subject[0] == '\0')
2739 subject = _("mail_va_new_email");
2741 gtk_window_set_title (GTK_WINDOW (window), subject);
2746 subject_field_changed (GtkEditable *editable,
2747 ModestMsgEditWindow *window)
2749 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2750 update_window_title (window);
2751 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2755 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2758 ModestMsgEditWindowPrivate *priv = NULL;
2760 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2761 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2763 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2765 gtk_widget_show_all (priv->find_toolbar);
2766 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2768 gtk_widget_hide_all (priv->find_toolbar);
2769 gtk_widget_grab_focus (priv->msg_body);
2775 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2777 GtkTextIter *match_start,
2778 GtkTextIter *match_end)
2780 GtkTextIter end_iter;
2781 gchar *str_casefold;
2784 gchar *range_casefold;
2787 gboolean result = FALSE;
2794 gtk_text_iter_forward_to_end (&end_iter);
2796 str_casefold = g_utf8_casefold (str, -1);
2797 str_chars_n = strlen (str);
2799 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2800 range_casefold = g_utf8_casefold (range_text, -1);
2801 range_chars_n = strlen (range_casefold);
2803 if (range_chars_n < str_chars_n) {
2804 g_free (str_casefold);
2805 g_free (range_text);
2806 g_free (range_casefold);
2810 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2811 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2812 if (!g_utf8_collate (range_subtext, str_casefold)) {
2813 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2815 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2816 match_start, match_end, NULL);
2817 g_free (found_text);
2819 g_free (range_subtext);
2823 g_free (str_casefold);
2824 g_free (range_text);
2825 g_free (range_casefold);
2832 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2833 ModestMsgEditWindow *window)
2835 gchar *current_search = NULL;
2836 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2838 GtkTextIter selection_start, selection_end;
2839 GtkTextIter match_start, match_end;
2840 gboolean continue_search = FALSE;
2842 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2843 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2844 g_free (current_search);
2845 g_free (priv->last_search);
2846 priv->last_search = NULL;
2847 /* Information banner about empty search */
2848 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2852 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2853 continue_search = TRUE;
2855 g_free (priv->last_search);
2856 priv->last_search = g_strdup (current_search);
2859 if (continue_search) {
2860 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2861 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2862 &match_start, &match_end);
2864 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2866 GtkTextIter buffer_start;
2867 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2868 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2869 &match_start, &match_end);
2871 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2874 /* Mark as selected the string found in search */
2876 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2877 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2879 g_free (priv->last_search);
2880 priv->last_search = NULL;
2882 g_free (current_search);
2886 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2887 ModestMsgEditWindow *window)
2889 GtkToggleAction *toggle;
2890 ModestWindowPrivate *parent_priv;
2891 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2893 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2894 gtk_toggle_action_set_active (toggle, FALSE);
2899 update_paste_dimming (ModestMsgEditWindow *window)
2901 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2902 GtkAction *action = NULL;
2903 GtkClipboard *clipboard = NULL;
2907 focused = gtk_window_get_focus (GTK_WINDOW (window));
2909 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2910 active = gtk_clipboard_wait_is_text_available (clipboard);
2913 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2917 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2918 gtk_action_set_sensitive (action, active);
2923 paste_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2925 GtkWidget *focused = gtk_window_get_focus (GTK_WINDOW (editor));
2927 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2928 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_unable_to_paste_here"));
2930 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ecoc_ib_edwin_nothing_to_paste"));
2935 copy_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2937 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_unable_to_copy"));
2943 modest_msg_edit_window_system_clipboard_owner_change (GtkClipboard *clipboard,
2945 ModestMsgEditWindow *window)
2947 update_paste_dimming (window);
2951 update_select_all_dimming (ModestMsgEditWindow *window)
2954 gboolean dimmed = FALSE;
2956 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2958 focused = gtk_window_get_focus (GTK_WINDOW (window));
2959 if (GTK_IS_ENTRY (focused)) {
2960 const gchar *current_text;
2961 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
2962 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
2963 } else if (GTK_IS_TEXT_VIEW (focused)) {
2964 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
2965 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
2966 } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
2969 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
2970 gtk_action_set_sensitive (action, !dimmed);
2974 update_zoom_dimming (ModestMsgEditWindow *window)
2977 gboolean dimmed = FALSE;
2979 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2981 focused = gtk_window_get_focus (GTK_WINDOW (window));
2982 dimmed = ! WP_IS_TEXT_VIEW (focused);
2983 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2984 gtk_action_set_sensitive (action, !dimmed);
2988 edit_menu_activated (GtkAction *action,
2991 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2993 update_select_all_dimming (window);
2996 view_menu_activated (GtkAction *action,
2999 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3001 update_zoom_dimming (window);
3005 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3007 ModestMsgEditWindowPrivate *priv;
3009 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3014 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3017 ModestMsgEditWindowPrivate *priv;
3019 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3025 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3028 ModestMsgEditWindowPrivate *priv;
3029 TnyHeader *header = NULL;
3031 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3032 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3034 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3035 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3037 if (priv->draft_msg != NULL) {
3038 header = tny_msg_get_header (priv->draft_msg);
3039 if (TNY_IS_HEADER (header)) {
3040 modest_window_mgr_unregister_header (mgr, header);
3042 g_object_unref (priv->draft_msg);
3045 if (draft != NULL) {
3046 g_object_ref (draft);
3047 header = tny_msg_get_header (draft);
3048 if (TNY_IS_HEADER (header))
3049 modest_window_mgr_register_header (mgr, header);
3052 priv->draft_msg = draft;