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 560
86 #define DEFAULT_FONT_SCALE 1.5
88 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
89 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
90 static void modest_msg_edit_window_finalize (GObject *obj);
92 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
93 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
94 static void send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
95 static void style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
96 static void setup_insensitive_handlers (ModestMsgEditWindow *editor);
97 static void reset_modified (ModestMsgEditWindow *editor);
99 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
100 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
101 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
102 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
103 GtkTextIter *start, GtkTextIter *end,
105 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
106 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
107 static void subject_field_insert_text (GtkEditable *editable,
109 gint new_text_length,
111 ModestMsgEditWindow *window);
112 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
114 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
116 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
118 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
119 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
120 GdkEventWindowState *event,
122 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
123 ModestRecptEditor *editor);
124 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
125 ModestMsgEditWindow *window);
127 /* ModestWindow methods implementation */
128 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
129 static void modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom);
130 static gdouble modest_msg_edit_window_get_zoom (ModestWindow *window);
131 static gboolean modest_msg_edit_window_zoom_minus (ModestWindow *window);
132 static gboolean modest_msg_edit_window_zoom_plus (ModestWindow *window);
133 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
134 gboolean show_toolbar);
135 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
137 ModestMsgEditWindow *window);
138 static void update_window_title (ModestMsgEditWindow *window);
139 static void update_dimmed (ModestMsgEditWindow *window);
140 static void update_paste_dimming (ModestMsgEditWindow *window);
141 static void update_copy_cut_dimming (ModestMsgEditWindow *window);
142 static void update_select_all_dimming (ModestMsgEditWindow *window);
143 static void update_zoom_dimming (ModestMsgEditWindow *window);
144 static void update_send_dimming (ModestMsgEditWindow *window);
147 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
148 ModestMsgEditWindow *window);
149 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
150 ModestMsgEditWindow *window);
151 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
153 GtkTextIter *match_start,
154 GtkTextIter *match_end);
156 static void DEBUG_BUFFER (WPTextBuffer *buffer)
161 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
162 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
163 while (!gtk_text_iter_is_end (&iter)) {
164 GString *output = g_string_new ("");
165 GSList *toggled_tags;
168 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
169 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
170 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
171 GtkTextTag *tag = (GtkTextTag *) node->data;
173 g_object_get (G_OBJECT (tag), "name", &name, NULL);
174 output = g_string_append (output, name);
175 g_string_append (output, " ");
177 output = g_string_append (output, "] OPENED [ ");
178 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
179 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
180 GtkTextTag *tag = (GtkTextTag *) node->data;
182 g_object_get (G_OBJECT (tag), "name", &name, NULL);
183 output = g_string_append (output, name);
184 g_string_append (output, " ");
186 output = g_string_append (output, "]\n");
187 g_message ("%s", output->str);
188 g_string_free (output, TRUE);
189 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
191 g_message ("END BUFFER");
196 /* static gboolean */
197 /* on_key_pressed (GtkWidget *self, */
198 /* GdkEventKey *event, */
199 /* gpointer user_data); */
201 static void edit_menu_activated (GtkAction *action,
203 static void view_menu_activated (GtkAction *action,
206 /* list my signals */
213 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
214 struct _ModestMsgEditWindowPrivate {
216 GtkWidget *header_box;
218 ModestPairList *from_field_protos;
219 GtkWidget *from_field;
223 GtkWidget *bcc_field;
224 GtkWidget *subject_field;
225 GtkWidget *attachments_view;
226 GtkWidget *priority_icon;
227 GtkWidget *add_attachment_button;
229 GtkWidget *cc_caption;
230 GtkWidget *bcc_caption;
231 gboolean update_caption_visibility;
232 GtkWidget *attachments_caption;
234 GtkTextBuffer *text_buffer;
236 GtkWidget *font_size_toolitem;
237 GtkWidget *font_face_toolitem;
238 GtkWidget *font_color_button;
239 GSList *font_items_group;
240 GtkWidget *font_tool_button_label;
241 GSList *size_items_group;
242 GtkWidget *size_tool_button_label;
244 GtkWidget *find_toolbar;
248 GtkWidget *scroll_area;
249 gint last_vadj_upper;
254 TnyHeaderFlags priority_flags;
258 gulong clipboard_change_handler_id;
267 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
268 MODEST_TYPE_MSG_EDIT_WINDOW, \
269 ModestMsgEditWindowPrivate))
271 static GtkWindowClass *parent_class = NULL;
273 /* uncomment the following if you have defined any signals */
274 /* static guint signals[LAST_SIGNAL] = {0}; */
277 modest_msg_edit_window_get_type (void)
279 static GType my_type = 0;
281 static const GTypeInfo my_info = {
282 sizeof(ModestMsgEditWindowClass),
283 NULL, /* base init */
284 NULL, /* base finalize */
285 (GClassInitFunc) modest_msg_edit_window_class_init,
286 NULL, /* class finalize */
287 NULL, /* class data */
288 sizeof(ModestMsgEditWindow),
290 (GInstanceInitFunc) modest_msg_edit_window_init,
293 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
294 "ModestMsgEditWindow",
297 wp_text_buffer_library_init ();
303 save_state (ModestWindow *self)
305 modest_widget_memory_save (modest_runtime_get_conf(),
306 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
311 restore_settings (ModestMsgEditWindow *self)
313 modest_widget_memory_restore (modest_runtime_get_conf(),
314 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
319 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
321 GObjectClass *gobject_class;
322 ModestWindowClass *modest_window_class;
323 gobject_class = (GObjectClass*) klass;
324 modest_window_class = (ModestWindowClass*) klass;
326 parent_class = g_type_class_peek_parent (klass);
327 gobject_class->finalize = modest_msg_edit_window_finalize;
329 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
330 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
331 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
332 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
333 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
334 modest_window_class->save_state_func = save_state;
335 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
337 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
341 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
343 ModestMsgEditWindowPrivate *priv;
344 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
346 priv->msg_body = NULL;
347 priv->from_field = NULL;
348 priv->to_field = NULL;
349 priv->cc_field = NULL;
350 priv->bcc_field = NULL;
351 priv->subject_field = NULL;
352 priv->attachments = NULL;
354 priv->zoom_level = 1.0;
356 priv->cc_caption = NULL;
357 priv->bcc_caption = NULL;
358 priv->update_caption_visibility = FALSE;
360 priv->priority_flags = 0;
362 priv->find_toolbar = NULL;
363 priv->last_search = NULL;
365 priv->draft_msg = NULL;
366 priv->outbox_msg = NULL;
367 priv->msg_uid = NULL;
368 priv->clipboard_change_handler_id = 0;
371 priv->last_vadj_upper = 0;
375 /* FIXME: this is a dup from the one in gtk/ */
378 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
380 static ModestPairList*
381 get_transports (void)
383 GSList *transports = NULL;
385 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
386 GSList *accounts = modest_account_mgr_account_names (account_mgr,
387 TRUE /* only enabled accounts. */);
389 GSList *cursor = accounts;
391 gchar *account_name = cursor->data;
392 gchar *from_string = NULL;
394 from_string = modest_account_mgr_get_from_string (account_mgr,
398 if (from_string && account_name) {
399 gchar *name = account_name;
400 ModestPair *pair = modest_pair_new ((gpointer) name,
401 (gpointer) from_string , TRUE);
402 transports = g_slist_prepend (transports, pair);
405 cursor = cursor->next;
407 g_slist_free (accounts); /* only free the accounts, not the elements,
408 * because they are used in the pairlist */
412 void vadj_changed (GtkAdjustment *adj,
413 ModestMsgEditWindow *window)
415 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
417 GdkRectangle rectangle, cursor_rectangle;
418 GtkTextIter position;
422 /* We detect if cursor is visible using the full height, not only the center. This
424 gtk_text_view_get_visible_rect (GTK_TEXT_VIEW (priv->msg_body), &rectangle);
425 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer),
427 gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer)));
428 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &position, &cursor_rectangle);
430 cursor_bottom = (cursor_rectangle.y + cursor_rectangle.height);
431 visible = (cursor_rectangle.y >= rectangle.y) && (cursor_bottom < (rectangle.y + rectangle.height));
433 if (gtk_widget_is_focus (priv->msg_body) &&
435 if (priv->last_vadj_upper != adj->upper) {
438 insert = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
439 gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (priv->msg_body),
440 insert, 0.1, FALSE, 0.0, 0.0);
443 priv->last_vadj_upper = adj->upper;
448 init_window (ModestMsgEditWindow *obj)
450 GtkWidget *from_caption, *to_caption, *subject_caption;
451 GtkWidget *main_vbox;
452 ModestMsgEditWindowPrivate *priv;
454 GtkSizeGroup *size_group;
456 GtkWidget *subject_box;
457 GtkWidget *attachment_icon;
458 GtkWidget *window_box;
459 #if (GTK_MINOR_VERSION >= 10)
460 GdkAtom deserialize_type;
462 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
464 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
466 /* Note: This ModestPairList* must exist for as long as the combo
467 * that uses it, because the ModestComboBox uses the ID opaquely,
468 * so it can't know how to manage its memory. */
469 priv->from_field_protos = get_transports ();
471 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
473 priv->to_field = modest_recpt_editor_new ();
474 priv->cc_field = modest_recpt_editor_new ();
475 priv->bcc_field = modest_recpt_editor_new ();
476 subject_box = gtk_hbox_new (FALSE, 0);
477 priv->priority_icon = gtk_image_new ();
478 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
479 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
480 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
481 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
482 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
483 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
484 priv->add_attachment_button = gtk_button_new ();
485 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
486 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
487 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
488 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
489 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
490 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
491 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
492 priv->attachments_view = modest_attachments_view_new (NULL);
494 priv->header_box = gtk_vbox_new (FALSE, 0);
496 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
497 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
498 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
499 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
500 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
501 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
502 g_object_unref (size_group);
504 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
505 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
506 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
507 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
508 gtk_size_group_add_widget (size_group, priv->subject_field);
509 gtk_size_group_add_widget (size_group, priv->attachments_view);
510 g_object_unref (size_group);
512 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
513 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
514 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
515 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
516 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
517 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
518 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
521 priv->msg_body = wp_text_view_new ();
522 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
523 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
524 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
525 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
526 #if (GTK_MINOR_VERSION >= 10)
527 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
528 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
530 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
531 deserialize_type, TRUE);
533 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
535 priv->find_toolbar = hildon_find_toolbar_new (NULL);
536 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
538 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
540 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
541 G_CALLBACK (text_buffer_refresh_attributes), obj);
542 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
543 G_CALLBACK (text_buffer_can_undo), obj);
544 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
545 G_CALLBACK (text_buffer_can_redo), obj);
546 g_signal_connect (G_OBJECT (obj), "window-state-event",
547 G_CALLBACK (modest_msg_edit_window_window_state_event),
549 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
550 G_CALLBACK (text_buffer_apply_tag), obj);
551 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
552 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
553 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
554 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
555 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
556 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
558 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
559 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
561 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
562 G_CALLBACK (msg_body_focus), obj);
563 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
564 G_CALLBACK (msg_body_focus), obj);
565 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
566 "changed", G_CALLBACK (recpt_field_changed), obj);
567 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
568 "changed", G_CALLBACK (recpt_field_changed), obj);
569 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
570 "changed", G_CALLBACK (recpt_field_changed), obj);
571 recpt_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
572 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
573 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
575 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
576 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
578 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
579 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
580 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
581 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
583 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
585 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
586 frame = gtk_frame_new (NULL);
587 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
589 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
590 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
591 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
593 G_CALLBACK (vadj_changed),
595 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
597 window_box = gtk_vbox_new (FALSE, 0);
598 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
599 gtk_container_add (GTK_CONTAINER(obj), window_box);
600 priv->scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
601 gtk_container_add (GTK_CONTAINER (frame), priv->scroll_area);
603 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
604 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
609 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
611 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
613 if (g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
614 priv->clipboard_change_handler_id))
615 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
616 priv->clipboard_change_handler_id);
620 modest_msg_edit_window_finalize (GObject *obj)
622 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
624 /* Sanity check: shouldn't be needed, the window mgr should
625 call this function before */
626 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
628 if (priv->draft_msg != NULL) {
629 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
630 if (TNY_IS_HEADER (header)) {
631 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
632 modest_window_mgr_unregister_header (mgr, header);
634 g_object_unref (priv->draft_msg);
635 priv->draft_msg = NULL;
637 if (priv->outbox_msg != NULL) {
638 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
639 if (TNY_IS_HEADER (header)) {
640 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
641 modest_window_mgr_unregister_header (mgr, header);
643 g_object_unref (priv->outbox_msg);
644 priv->outbox_msg = NULL;
646 if (priv->msg_uid != NULL) {
647 g_free (priv->msg_uid);
648 priv->msg_uid = NULL;
651 /* This had to stay alive for as long as the combobox that used it: */
652 modest_pair_list_free (priv->from_field_protos);
654 G_OBJECT_CLASS(parent_class)->finalize (obj);
658 menubar_to_menu (GtkUIManager *ui_manager)
660 GtkWidget *main_menu;
664 /* Create new main menu */
665 main_menu = gtk_menu_new();
667 /* Get the menubar from the UI manager */
668 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
670 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
674 menu = GTK_WIDGET (iter->data);
675 gtk_widget_reparent(menu, main_menu);
677 iter = g_list_next (iter);
683 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type)
685 GdkPixbufLoader *loader;
688 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
693 tny_stream_reset (TNY_STREAM (stream));
694 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
695 unsigned char read_buffer[128];
697 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
698 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
702 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
703 g_object_ref (pixbuf);
704 gdk_pixbuf_loader_close (loader, NULL);
705 g_object_unref (loader);
707 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
708 GdkPixbuf *new_pixbuf;
710 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
711 gdk_pixbuf_get_width (pixbuf);
712 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
713 g_object_unref (pixbuf);
721 replace_with_attachments (ModestMsgEditWindow *self, GList *attachments)
723 ModestMsgEditWindowPrivate *priv;
726 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
728 for (node = attachments; node != NULL; node = g_list_next (node)) {
729 TnyMimePart *part = (TnyMimePart *) node->data;
730 const gchar *cid = tny_mime_part_get_content_id (part);
731 const gchar *mime_type = tny_mime_part_get_content_type (part);
732 if ((cid != NULL)&&(mime_type != NULL)) {
733 TnyStream *stream = tny_mime_part_get_stream (part);
734 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type);
735 g_object_unref (stream);
737 if (pixbuf != NULL) {
738 /* wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf); */
739 g_object_unref (pixbuf);
746 update_last_cid (ModestMsgEditWindow *self, GList *attachments)
749 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
751 for (node = attachments; node != NULL; node = g_list_next (node)) {
752 TnyMimePart *part = (TnyMimePart *) node->data;
753 const gchar *cid = tny_mime_part_get_content_id (part);
755 char *invalid = NULL;
756 gint int_cid = strtol (cid, &invalid, 10);
757 if ((invalid != NULL) && (*invalid == '\0') && (int_cid > priv->last_cid)) {
758 priv->last_cid = int_cid;
766 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
769 const gchar *to, *cc, *bcc, *subject;
771 ModestMsgEditWindowPrivate *priv;
773 TnyHeaderFlags priority_flags;
774 TnyFolder *msg_folder;
775 gboolean is_html = FALSE;
777 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
778 g_return_if_fail (TNY_IS_MSG (msg));
780 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
782 header = tny_msg_get_header (msg);
783 to = tny_header_get_to (header);
784 cc = tny_header_get_cc (header);
785 bcc = tny_header_get_bcc (header);
786 subject = tny_header_get_subject (header);
787 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
790 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
792 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
793 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
794 gtk_widget_show (priv->cc_caption);
795 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
796 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
797 gtk_widget_hide (priv->cc_caption);
800 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
801 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
802 gtk_widget_show (priv->bcc_caption);
803 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
804 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
805 gtk_widget_hide (priv->bcc_caption);
808 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
809 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
812 update_window_title (self);
814 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
815 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
817 if ((body == NULL)||(body[0] == '\0')) {
819 body = modest_text_utils_convert_to_html ("");
822 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
823 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
826 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
829 if (preserve_is_rich && !is_html) {
830 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
831 /* Get the default format required from configuration */
832 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
833 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
836 /* Set the default focus depending on having already a To: field or not */
837 if ((!to)||(*to == '\0')) {
838 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
840 gtk_widget_grab_focus (priv->msg_body);
843 /* TODO: lower priority, select in the From: combo to the
844 value that comes from msg <- not sure, should it be
847 /* Add attachments to the view */
848 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
849 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
850 if (priv->attachments == NULL) {
851 gtk_widget_hide (priv->attachments_caption);
853 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
854 gtk_widget_show_all (priv->attachments_caption);
855 replace_with_attachments (self, priv->attachments);
857 update_last_cid (self, priv->attachments);
859 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
861 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
862 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
864 reset_modified (self);
866 update_dimmed (self);
867 text_buffer_can_undo (priv->text_buffer, FALSE, self);
868 text_buffer_can_redo (priv->text_buffer, FALSE, self);
871 g_free (priv->msg_uid);
872 priv->msg_uid = NULL;
875 /* we should set a reference to the incoming message if it is a draft */
876 msg_folder = tny_msg_get_folder (msg);
878 if (modest_tny_folder_is_local_folder (msg_folder)) {
879 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
880 if (type == TNY_FOLDER_TYPE_DRAFTS)
881 priv->draft_msg = g_object_ref(msg);
882 if (type == TNY_FOLDER_TYPE_OUTBOX)
883 priv->outbox_msg = g_object_ref(msg);
884 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
886 g_object_unref (msg_folder);
891 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
894 GList *item_children, *node;
895 GtkWidget *bin_child;
897 bin_child = gtk_bin_get_child (GTK_BIN(item));
899 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
901 for (node = item_children; node != NULL; node = g_list_next (node)) {
902 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
903 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
906 g_list_free (item_children);
910 menu_tool_button_dont_expand (GtkMenuToolButton *item)
913 GList *item_children, *node;
915 box = gtk_bin_get_child (GTK_BIN (item));
916 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
917 item_children = gtk_container_get_children (GTK_CONTAINER (box));
919 for (node = item_children; node != NULL; node = g_list_next (node)) {
920 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
921 if (GTK_IS_TOGGLE_BUTTON (node->data))
922 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
923 else if (GTK_IS_BUTTON (node->data))
924 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
926 g_list_free (item_children);
931 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
933 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
934 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
935 GtkWidget *placeholder;
936 GtkWidget *tool_item;
941 GtkWidget *sizes_menu;
942 GtkWidget *fonts_menu;
943 GSList *radio_group = NULL;
948 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
949 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
951 /* should we hide the toolbar? */
952 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
953 gtk_widget_hide (parent_priv->toolbar);
955 /* Font color placeholder */
956 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
957 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
960 tool_item = GTK_WIDGET (gtk_tool_item_new ());
961 priv->font_color_button = hildon_color_button_new ();
962 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
963 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
964 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
965 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
966 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
967 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
968 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
970 /* Font size and face placeholder */
971 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
972 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
974 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
975 priv->size_tool_button_label = gtk_label_new (NULL);
976 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
977 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
978 size_text,"</span>", NULL);
979 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
981 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
982 sizes_menu = gtk_menu_new ();
983 priv->size_items_group = NULL;
985 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
986 GtkWidget *size_menu_item;
988 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
989 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
990 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
991 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
992 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
993 gtk_widget_show (size_menu_item);
995 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
999 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1000 GtkWidget *item = (GtkWidget *) node->data;
1001 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1005 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1006 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1007 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1008 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1009 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1010 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1011 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1012 priv->font_size_toolitem = tool_item;
1015 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1016 priv->font_tool_button_label = gtk_label_new (NULL);
1017 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1018 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1020 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1021 fonts_menu = gtk_menu_new ();
1022 priv->font_items_group = NULL;
1024 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1025 GtkWidget *font_menu_item;
1026 GtkWidget *child_label;
1028 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1029 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1030 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1031 wp_get_font_name (font_index), "</span>", NULL);
1032 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1035 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1036 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1037 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1038 gtk_widget_show (font_menu_item);
1040 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1043 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1044 GtkWidget *item = (GtkWidget *) node->data;
1045 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1048 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1049 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1050 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1051 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1052 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1053 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1054 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1055 priv->font_face_toolitem = tool_item;
1057 /* Set expand and homogeneous for remaining items */
1058 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1059 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1060 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1061 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1062 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1063 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1064 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1065 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1066 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1074 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1077 ModestWindowPrivate *parent_priv;
1078 ModestMsgEditWindowPrivate *priv;
1079 GtkActionGroup *action_group;
1080 GError *error = NULL;
1081 GdkPixbuf *window_icon = NULL;
1084 gboolean prefer_formatted;
1086 ModestPair *account_pair = NULL;
1088 g_return_val_if_fail (msg, NULL);
1089 g_return_val_if_fail (account_name, NULL);
1091 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
1093 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1094 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1096 parent_priv->ui_manager = gtk_ui_manager_new();
1097 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
1098 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1100 /* Add common actions */
1101 gtk_action_group_add_actions (action_group,
1102 modest_msg_edit_action_entries,
1103 G_N_ELEMENTS (modest_msg_edit_action_entries),
1105 gtk_action_group_add_toggle_actions (action_group,
1106 modest_msg_edit_toggle_action_entries,
1107 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
1109 gtk_action_group_add_radio_actions (action_group,
1110 modest_msg_edit_alignment_radio_action_entries,
1111 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
1113 G_CALLBACK (modest_ui_actions_on_change_justify),
1115 gtk_action_group_add_radio_actions (action_group,
1116 modest_msg_edit_zoom_action_entries,
1117 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
1119 G_CALLBACK (modest_ui_actions_on_change_zoom),
1121 gtk_action_group_add_radio_actions (action_group,
1122 modest_msg_edit_priority_action_entries,
1123 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
1125 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
1127 gtk_action_group_add_radio_actions (action_group,
1128 modest_msg_edit_file_format_action_entries,
1129 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
1130 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
1131 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
1133 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1134 g_object_unref (action_group);
1136 /* Load the UI definition */
1137 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
1139 if (error != NULL) {
1140 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
1141 g_clear_error (&error);
1144 /* Add accelerators */
1145 gtk_window_add_accel_group (GTK_WINDOW (obj),
1146 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1149 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
1150 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1153 init_window (MODEST_MSG_EDIT_WINDOW(obj));
1155 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1157 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1159 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1160 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1162 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
1164 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
1165 if (account_pair != NULL)
1166 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
1168 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1170 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1172 /* Set window icon */
1173 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
1175 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1176 g_object_unref (window_icon);
1179 /* Dim at start clipboard actions */
1180 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
1181 gtk_action_set_sensitive (action, FALSE);
1182 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
1183 gtk_action_set_sensitive (action, FALSE);
1184 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
1185 gtk_action_set_sensitive (action, FALSE);
1187 /* Update select all */
1188 update_select_all_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1189 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu");
1190 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (edit_menu_activated), obj);
1191 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu");
1192 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (view_menu_activated), obj);
1194 /* set initial state of cc and bcc */
1195 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
1196 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1197 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
1198 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
1199 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1200 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
1202 /* Setup the file format */
1203 conf = modest_runtime_get_conf ();
1204 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
1206 g_clear_error (&error);
1207 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
1209 file_format = (prefer_formatted) ?
1210 MODEST_FILE_FORMAT_FORMATTED_TEXT :
1211 MODEST_FILE_FORMAT_PLAIN_TEXT;
1212 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
1214 update_paste_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1215 priv->update_caption_visibility = TRUE;
1217 reset_modified (MODEST_MSG_EDIT_WINDOW (obj));
1219 return (ModestWindow*) obj;
1223 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1225 GString **string_buffer = (GString **) user_data;
1227 *string_buffer = g_string_append (*string_buffer, buffer);
1233 * @result: A new string which should be freed with g_free().
1236 get_formatted_data (ModestMsgEditWindow *edit_window)
1238 ModestMsgEditWindowPrivate *priv;
1239 GString *string_buffer = g_string_new ("");
1241 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1243 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1245 return g_string_free (string_buffer, FALSE);
1250 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1253 const gchar *account_name;
1254 ModestMsgEditWindowPrivate *priv;
1256 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1258 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1260 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1261 g_return_val_if_fail (account_name, NULL);
1264 /* don't free these (except from) */
1265 data = g_slice_new0 (MsgData);
1266 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1268 data->account_name = g_strdup (account_name);
1269 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1270 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1271 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1272 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1273 if (priv->draft_msg) {
1274 data->draft_msg = g_object_ref (priv->draft_msg);
1275 } else if (priv->outbox_msg) {
1276 data->draft_msg = g_object_ref (priv->outbox_msg);
1278 data->draft_msg = NULL;
1281 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1283 gtk_text_buffer_get_bounds (buf, &b, &e);
1284 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1286 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1287 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1289 data->html_body = NULL;
1291 /* deep-copy the data */
1292 GList *cursor = priv->attachments;
1293 data->attachments = NULL;
1295 if (!(TNY_IS_MIME_PART(cursor->data))) {
1296 g_warning ("strange data in attachment list");
1297 cursor = g_list_next (cursor);
1300 data->attachments = g_list_append (data->attachments,
1301 g_object_ref (cursor->data));
1302 cursor = g_list_next (cursor);
1305 data->priority_flags = priv->priority_flags;
1312 unref_gobject (GObject *obj, gpointer data)
1314 if (!G_IS_OBJECT(obj))
1316 g_object_unref (obj);
1320 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1323 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1331 g_free (data->subject);
1332 g_free (data->plain_body);
1333 g_free (data->html_body);
1334 g_free (data->account_name);
1336 if (data->draft_msg != NULL) {
1337 g_object_unref (data->draft_msg);
1338 data->draft_msg = NULL;
1341 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1342 g_list_free (data->attachments);
1344 g_slice_free (MsgData, data);
1348 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1351 ModestMsgEditWindowPrivate *priv = NULL;
1352 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1354 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1356 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1358 return MODEST_MSG_EDIT_FORMAT_HTML;
1360 return MODEST_MSG_EDIT_FORMAT_TEXT;
1364 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1365 ModestMsgEditFormat format)
1367 ModestMsgEditWindowPrivate *priv;
1369 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1370 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1373 case MODEST_MSG_EDIT_FORMAT_HTML:
1374 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1376 case MODEST_MSG_EDIT_FORMAT_TEXT:
1377 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1380 g_return_if_reached ();
1384 ModestMsgEditFormatState *
1385 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1387 ModestMsgEditFormatState *format_state = NULL;
1388 ModestMsgEditWindowPrivate *priv;
1389 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1391 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1392 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1394 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1396 format_state = g_new0 (ModestMsgEditFormatState, 1);
1397 format_state->bold = buffer_format->bold&0x1;
1398 format_state->italics = buffer_format->italic&0x1;
1399 format_state->bullet = buffer_format->bullet&0x1;
1400 format_state->color = buffer_format->color;
1401 format_state->font_size = buffer_format->font_size;
1402 format_state->font_family = wp_get_font_name (buffer_format->font);
1403 format_state->justification = buffer_format->justification;
1404 g_free (buffer_format);
1406 return format_state;
1411 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1412 const ModestMsgEditFormatState *format_state)
1414 ModestMsgEditWindowPrivate *priv;
1415 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1416 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1417 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1418 g_return_if_fail (format_state != NULL);
1420 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1421 gtk_widget_grab_focus (priv->msg_body);
1422 buffer_format->bold = (format_state->bold != FALSE);
1423 buffer_format->italic = (format_state->italics != FALSE);
1424 buffer_format->color = format_state->color;
1425 buffer_format->font_size = format_state->font_size;
1426 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1427 buffer_format->justification = format_state->justification;
1428 buffer_format->bullet = format_state->bullet;
1430 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1432 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1433 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1434 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1435 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1436 buffer_format->cs.font = (buffer_format->font != current_format->font);
1437 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1438 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1440 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1441 if (buffer_format->cs.bold) {
1442 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1444 if (buffer_format->cs.italic) {
1445 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1447 if (buffer_format->cs.color) {
1448 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1450 if (buffer_format->cs.font_size) {
1451 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1453 if (buffer_format->cs.justification) {
1454 switch (buffer_format->justification) {
1455 case GTK_JUSTIFY_LEFT:
1456 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1458 case GTK_JUSTIFY_CENTER:
1459 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1461 case GTK_JUSTIFY_RIGHT:
1462 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1469 if (buffer_format->cs.font) {
1470 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1472 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1473 if (buffer_format->cs.bullet) {
1474 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((buffer_format->bullet)?1:0));
1476 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1478 g_free (current_format);
1483 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1485 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1487 ModestWindowPrivate *parent_priv;
1488 ModestMsgEditWindowPrivate *priv;
1489 GtkWidget *new_size_menuitem;
1490 GtkWidget *new_font_menuitem;
1492 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1493 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1495 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1496 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1497 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1498 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1500 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1501 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1502 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1505 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1507 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1508 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1510 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1511 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1513 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1514 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1516 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1517 G_CALLBACK (modest_msg_edit_window_color_button_change),
1519 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1520 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1521 G_CALLBACK (modest_msg_edit_window_color_button_change),
1524 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1525 buffer_format->font_size))->data);
1526 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1530 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1531 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1532 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1534 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1535 G_CALLBACK (modest_msg_edit_window_size_change),
1537 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1538 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1539 G_CALLBACK (modest_msg_edit_window_size_change),
1543 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1544 buffer_format->font))->data);
1545 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1549 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1550 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1551 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1553 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1554 G_CALLBACK (modest_msg_edit_window_font_change),
1556 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1557 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1558 G_CALLBACK (modest_msg_edit_window_font_change),
1562 g_free (buffer_format);
1568 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1571 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1572 ModestMsgEditWindowPrivate *priv;
1573 GtkWidget *dialog = NULL;
1575 const GdkColor *new_color = NULL;
1577 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1578 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1580 #ifdef MODEST_HILDON_VERSION_0
1581 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1582 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1584 dialog = hildon_color_chooser_new ();
1585 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1586 #endif /*MODEST_HILDON_VERSION_0*/
1587 g_free (buffer_format);
1589 response = gtk_dialog_run (GTK_DIALOG (dialog));
1591 case GTK_RESPONSE_OK: {
1592 #ifdef MODEST_HILDON_VERSION_0
1593 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1596 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1598 #endif /*MODEST_HILDON_VERSION_0*/
1605 gtk_widget_destroy (dialog);
1607 if (new_color != NULL)
1608 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1613 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1616 ModestMsgEditWindowPrivate *priv;
1617 GtkWidget *dialog = NULL;
1619 GdkColor *old_color = NULL;
1620 const GdkColor *new_color = NULL;
1622 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1623 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1625 #ifdef MODEST_HILDON_VERSION_0
1626 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1627 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1629 dialog = hildon_color_chooser_new ();
1630 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1631 #endif /*MODEST_HILDON_VERSION_9*/
1633 response = gtk_dialog_run (GTK_DIALOG (dialog));
1635 case GTK_RESPONSE_OK: {
1636 #ifdef MODEST_HILDON_VERSION_0
1637 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1640 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1642 #endif /*MODEST_HILDON_VERSION_0*/
1648 gtk_widget_destroy (dialog);
1650 if (new_color != NULL)
1651 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1655 static TnyStream* create_stream_for_uri (const gchar* uri)
1660 TnyStream *result = NULL;
1662 GnomeVFSHandle *handle = NULL;
1663 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1664 if (test == GNOME_VFS_OK) {
1665 /* Create the tinymail stream: */
1666 /* Presumably tinymai will call gnome_vfs_close (handle) later. */
1667 result = TNY_STREAM (tny_vfs_stream_new (handle));
1674 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1677 ModestMsgEditWindowPrivate *priv;
1678 GtkWidget *dialog = NULL;
1680 GSList *uris = NULL;
1681 GSList *uri_node = NULL;
1683 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1685 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1686 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1687 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1689 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1691 response = gtk_dialog_run (GTK_DIALOG (dialog));
1693 case GTK_RESPONSE_OK:
1694 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1699 gtk_widget_destroy (dialog);
1701 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1703 GnomeVFSHandle *handle = NULL;
1704 GnomeVFSResult result;
1705 GtkTextIter position;
1706 GtkTextMark *insert_mark;
1708 uri = (const gchar *) uri_node->data;
1709 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1710 if (result == GNOME_VFS_OK) {
1712 GnomeVFSFileInfo info;
1713 gchar *filename, *basename, *escaped_filename;
1714 TnyMimePart *mime_part;
1716 const gchar *mime_type = NULL;
1717 GnomeVFSURI *vfs_uri;
1719 vfs_uri = gnome_vfs_uri_new (uri);
1721 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1722 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1723 g_free (escaped_filename);
1724 gnome_vfs_uri_unref (vfs_uri);
1726 if (gnome_vfs_get_file_info (uri, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
1727 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1729 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1731 mime_part = tny_platform_factory_new_mime_part
1732 (modest_runtime_get_platform_factory ());
1734 TnyStream *stream = create_stream_for_uri (uri);
1735 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1737 content_id = g_strdup_printf ("%d", priv->last_cid);
1738 tny_mime_part_set_content_id (mime_part, content_id);
1739 g_free (content_id);
1742 basename = g_path_get_basename (filename);
1743 tny_mime_part_set_filename (mime_part, basename);
1746 pixbuf = pixbuf_from_stream (stream, mime_type);
1748 if (pixbuf != NULL) {
1749 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1750 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1751 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1754 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1755 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1757 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1758 gtk_widget_show_all (priv->attachments_caption);
1759 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1769 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
1772 ModestMsgEditWindowPrivate *priv;
1773 GtkWidget *dialog = NULL;
1775 GSList *uris = NULL;
1778 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1780 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1781 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
1782 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1784 response = gtk_dialog_run (GTK_DIALOG (dialog));
1786 case GTK_RESPONSE_OK:
1787 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1792 gtk_widget_destroy (dialog);
1794 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1795 const gchar *uri = (const gchar *) uri_node->data;
1796 modest_msg_edit_window_attach_file_one (window, uri);
1798 g_slist_foreach (uris, (GFunc) g_free, NULL);
1799 g_slist_free (uris);
1803 modest_msg_edit_window_attach_file_one (
1804 ModestMsgEditWindow *window,
1807 g_return_if_fail (window);
1808 g_return_if_fail (uri);
1810 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1813 GnomeVFSHandle *handle = NULL;
1814 GnomeVFSResult result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1815 if (result == GNOME_VFS_OK) {
1816 TnyMimePart *mime_part;
1818 const gchar *mime_type = NULL;
1820 gchar *escaped_filename;
1823 GnomeVFSFileInfo info;
1824 GnomeVFSURI *vfs_uri;
1826 vfs_uri = gnome_vfs_uri_new (uri);
1829 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1830 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1831 g_free (escaped_filename);
1832 gnome_vfs_uri_unref (vfs_uri);
1834 if (gnome_vfs_get_file_info (uri,
1836 GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
1837 GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1839 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1840 mime_part = tny_platform_factory_new_mime_part
1841 (modest_runtime_get_platform_factory ());
1842 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1844 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1846 content_id = g_strdup_printf ("%d", priv->last_cid);
1847 tny_mime_part_set_content_id (mime_part, content_id);
1848 g_free (content_id);
1851 basename = g_path_get_basename (filename);
1852 tny_mime_part_set_filename (mime_part, basename);
1855 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1856 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1858 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1859 gtk_widget_show_all (priv->attachments_caption);
1860 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1866 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1869 ModestMsgEditWindowPrivate *priv;
1870 gboolean clean_list = FALSE;
1872 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1873 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1875 if (att_list == NULL) {
1876 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1880 if (att_list == NULL) {
1881 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1883 GtkWidget *confirmation_dialog = NULL;
1884 gboolean dialog_response;
1886 gchar *message = NULL;
1887 const gchar *filename = NULL;
1889 if (att_list->next == NULL) {
1890 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1894 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1895 att_list->next == NULL), filename);
1896 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1898 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1899 gtk_widget_destroy (confirmation_dialog);
1900 if (!dialog_response) {
1902 g_list_free (att_list);
1905 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1907 for (node = att_list; node != NULL; node = g_list_next (node)) {
1908 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1909 const gchar *att_id;
1910 priv->attachments = g_list_remove (priv->attachments, mime_part);
1912 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1914 if (priv->attachments == NULL)
1915 gtk_widget_hide (priv->attachments_caption);
1916 att_id = tny_mime_part_get_content_id (mime_part);
1918 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1920 g_object_unref (mime_part);
1921 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1926 g_list_free (att_list);
1930 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1933 ModestMsgEditWindowPrivate *priv;
1934 GdkColor *new_color;
1935 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1937 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1938 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1941 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1943 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1945 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1947 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1952 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1955 ModestMsgEditWindowPrivate *priv;
1956 gint new_size_index;
1957 ModestMsgEditWindow *window;
1960 window = MODEST_MSG_EDIT_WINDOW (userdata);
1961 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1962 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1964 if (gtk_check_menu_item_get_active (menu_item)) {
1966 WPTextBufferFormat format;
1968 memset (&format, 0, sizeof (format));
1969 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1971 label = gtk_bin_get_child (GTK_BIN (menu_item));
1973 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1974 format.cs.font_size = TRUE;
1975 format.cs.text_position = TRUE;
1976 format.cs.font = TRUE;
1977 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1978 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1980 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1981 (gpointer) wp_get_font_size_index (new_size_index, 12)))
1982 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1984 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1985 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1986 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1992 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1995 ModestMsgEditWindowPrivate *priv;
1996 gint new_font_index;
1997 ModestMsgEditWindow *window;
2000 window = MODEST_MSG_EDIT_WINDOW (userdata);
2001 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2002 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2004 if (gtk_check_menu_item_get_active (menu_item)) {
2007 label = gtk_bin_get_child (GTK_BIN (menu_item));
2009 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2011 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2012 (gpointer) new_font_index))
2013 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2015 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2016 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2017 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2023 modest_msg_edit_window_set_zoom (ModestWindow *window,
2026 ModestMsgEditWindowPrivate *priv;
2027 ModestWindowPrivate *parent_priv;
2028 GtkRadioAction *zoom_radio_action;
2030 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2032 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2033 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2034 priv->zoom_level = zoom;
2035 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom*DEFAULT_FONT_SCALE);
2037 /* Zoom level menu options should be updated with the current zoom level */
2038 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2039 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2040 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2041 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2042 /* FIXME: Not availible before Gtk 2.10 */
2044 gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
2049 modest_msg_edit_window_get_zoom (ModestWindow *window)
2051 ModestMsgEditWindowPrivate *priv;
2053 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
2055 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2056 return priv->zoom_level;
2060 zoom_allowed (ModestMsgEditWindow *window)
2064 focus = gtk_window_get_focus (GTK_WINDOW (window));
2065 return (focus != NULL && WP_IS_TEXT_VIEW (focus));
2069 modest_msg_edit_window_zoom_plus (ModestWindow *window)
2071 ModestWindowPrivate *parent_priv;
2072 GtkRadioAction *zoom_radio_action;
2073 GSList *group, *node;
2075 /* First we check if the text view is focused. If not, zooming is not allowed */
2076 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2077 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2081 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2082 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2083 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2085 group = gtk_radio_action_get_group (zoom_radio_action);
2087 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
2088 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
2092 for (node = group; node != NULL; node = g_slist_next (node)) {
2093 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
2094 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
2102 modest_msg_edit_window_zoom_minus (ModestWindow *window)
2104 ModestWindowPrivate *parent_priv;
2105 GtkRadioAction *zoom_radio_action;
2106 GSList *group, *node;
2108 /* First we check if the text view is focused. If not, zooming is not allowed */
2109 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2110 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2114 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2115 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2116 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2118 group = gtk_radio_action_get_group (zoom_radio_action);
2120 for (node = group; node != NULL; node = g_slist_next (node)) {
2121 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
2122 if (node->next != NULL) {
2123 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
2126 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
2134 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2136 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2137 ModestWindowPrivate *parent_priv;
2138 ModestWindowMgr *mgr;
2139 gboolean is_fullscreen;
2140 GtkAction *fs_toggle_action;
2143 mgr = modest_runtime_get_window_mgr ();
2144 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2146 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2148 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2149 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2150 if (is_fullscreen != active)
2151 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2159 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
2161 ModestWindowPrivate *parent_priv;
2162 GtkAction *fs_toggle_action;
2165 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2167 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2168 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
2169 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
2173 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2176 ModestMsgEditWindowPrivate *priv = NULL;
2177 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2179 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2180 if (!priv->update_caption_visibility)
2183 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2185 gtk_widget_show (priv->cc_caption);
2187 gtk_widget_hide (priv->cc_caption);
2189 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2193 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2196 ModestMsgEditWindowPrivate *priv = NULL;
2197 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2199 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2200 if (!priv->update_caption_visibility)
2203 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2205 gtk_widget_show (priv->bcc_caption);
2207 gtk_widget_hide (priv->bcc_caption);
2209 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2213 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2214 ModestRecptEditor *editor)
2216 ModestMsgEditWindowPrivate *priv;
2218 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2219 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2220 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2222 if (editor == NULL) {
2223 GtkWidget *view_focus;
2224 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2226 /* This code should be kept in sync with ModestRecptEditor. The
2227 textview inside the recpt editor is the one that really gets the
2228 focus. As it's inside a scrolled window, and this one inside the
2229 hbox recpt editor inherits from, we'll need to go up in the
2230 hierarchy to know if the text view is part of the recpt editor
2231 or if it's a different text entry */
2233 if (gtk_widget_get_parent (view_focus)) {
2234 GtkWidget *first_parent;
2236 first_parent = gtk_widget_get_parent (view_focus);
2237 if (gtk_widget_get_parent (first_parent) &&
2238 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2239 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2244 editor = MODEST_RECPT_EDITOR (priv->to_field);
2248 modest_address_book_select_addresses (editor);
2253 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2255 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2257 modest_msg_edit_window_open_addressbook (window, NULL);
2261 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2262 gboolean show_toolbar)
2264 ModestWindowPrivate *parent_priv;
2266 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2267 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2269 /* FIXME: we can not just use the code of
2270 modest_msg_edit_window_setup_toolbar because it has a
2271 mixture of both initialization and creation code. */
2274 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2276 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2280 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2281 TnyHeaderFlags priority_flags)
2283 ModestMsgEditWindowPrivate *priv;
2284 ModestWindowPrivate *parent_priv;
2286 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2288 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2289 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2290 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2292 if (priv->priority_flags != priority_flags) {
2293 GtkAction *priority_action = NULL;
2295 priv->priority_flags = priority_flags;
2297 switch (priority_flags) {
2298 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2299 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2300 gtk_widget_show (priv->priority_icon);
2301 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2302 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2304 case TNY_HEADER_FLAG_LOW_PRIORITY:
2305 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2306 gtk_widget_show (priv->priority_icon);
2307 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2308 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2311 gtk_widget_hide (priv->priority_icon);
2312 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2313 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2316 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2317 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2322 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2325 ModestMsgEditWindowPrivate *priv;
2326 ModestWindowPrivate *parent_priv;
2327 gint current_format;
2329 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2331 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2332 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2334 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2335 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2337 if (current_format != file_format) {
2338 switch (file_format) {
2339 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2340 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2342 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2346 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2347 response = gtk_dialog_run (GTK_DIALOG (dialog));
2348 gtk_widget_destroy (dialog);
2349 if (response == GTK_RESPONSE_OK) {
2350 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2352 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2353 modest_maemo_toggle_action_set_active_block_notify (action, TRUE);
2358 update_dimmed (window);
2363 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2366 ModestMsgEditWindowPrivate *priv;
2367 WPTextBufferFormat oldfmt, fmt;
2368 gint old_position = 0;
2372 GdkColor *color = NULL;
2373 gboolean bold, bold_set, italic, italic_set;
2374 gboolean underline, underline_set;
2375 gboolean strikethrough, strikethrough_set;
2376 gboolean position_set;
2377 gboolean font_size_set, font_set, color_set;
2380 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2381 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2383 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2385 /* First we get the currently selected font information */
2386 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2387 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2389 switch (oldfmt.text_position) {
2390 case TEXT_POSITION_NORMAL:
2393 case TEXT_POSITION_SUPERSCRIPT:
2401 g_object_set (G_OBJECT (dialog),
2402 "bold", oldfmt.bold != FALSE,
2403 "bold-set", !oldfmt.cs.bold,
2404 "underline", oldfmt.underline != FALSE,
2405 "underline-set", !oldfmt.cs.underline,
2406 "italic", oldfmt.italic != FALSE,
2407 "italic-set", !oldfmt.cs.italic,
2408 "strikethrough", oldfmt.strikethrough != FALSE,
2409 "strikethrough-set", !oldfmt.cs.strikethrough,
2410 "color", &oldfmt.color,
2411 "color-set", !oldfmt.cs.color,
2412 "size", wp_font_size[oldfmt.font_size],
2413 "size-set", !oldfmt.cs.font_size,
2414 "position", old_position,
2415 "position-set", !oldfmt.cs.text_position,
2416 "family", wp_get_font_name (oldfmt.font),
2417 "family-set", !oldfmt.cs.font,
2420 gtk_widget_show_all (dialog);
2421 response = gtk_dialog_run (GTK_DIALOG (dialog));
2422 if (response == GTK_RESPONSE_OK) {
2424 g_object_get( dialog,
2426 "bold-set", &bold_set,
2427 "underline", &underline,
2428 "underline-set", &underline_set,
2430 "italic-set", &italic_set,
2431 "strikethrough", &strikethrough,
2432 "strikethrough-set", &strikethrough_set,
2434 "color-set", &color_set,
2436 "size-set", &font_size_set,
2437 "family", &font_name,
2438 "family-set", &font_set,
2439 "position", &position,
2440 "position-set", &position_set,
2445 if (response == GTK_RESPONSE_OK) {
2446 memset(&fmt, 0, sizeof(fmt));
2452 fmt.italic = italic;
2453 fmt.cs.italic = TRUE;
2455 if (underline_set) {
2456 fmt.underline = underline;
2457 fmt.cs.underline = TRUE;
2459 if (strikethrough_set) {
2460 fmt.strikethrough = strikethrough;
2461 fmt.cs.strikethrough = TRUE;
2466 ? TEXT_POSITION_NORMAL
2467 : ( ( position == 1 )
2468 ? TEXT_POSITION_SUPERSCRIPT
2469 : TEXT_POSITION_SUBSCRIPT );
2470 fmt.cs.text_position = TRUE;
2474 fmt.cs.color = TRUE;
2477 fmt.font = wp_get_font_index(font_name,
2482 if (font_size_set) {
2483 fmt.font_size = wp_get_font_size_index(
2484 font_size, DEFAULT_FONT_SIZE);
2485 fmt.cs.font_size = TRUE;
2487 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2489 gtk_widget_destroy (dialog);
2491 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2495 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2497 ModestMsgEditWindowPrivate *priv;
2499 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2500 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2502 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2504 update_dimmed (window);
2509 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2511 ModestMsgEditWindowPrivate *priv;
2513 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2514 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2516 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2518 update_dimmed (window);
2523 update_dimmed (ModestMsgEditWindow *window)
2525 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2526 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2530 gboolean editor_focused;
2532 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2533 editor_focused = gtk_widget_is_focus (priv->msg_body);
2535 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2536 gtk_action_set_sensitive (action, rich_text && editor_focused);
2537 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2538 gtk_action_set_sensitive (action, rich_text && editor_focused);
2539 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2540 gtk_action_set_sensitive (action, rich_text && editor_focused);
2541 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2542 gtk_action_set_sensitive (action, rich_text && editor_focused);
2543 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2544 gtk_action_set_sensitive (action, rich_text && editor_focused);
2545 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2546 gtk_action_set_sensitive (action, rich_text && editor_focused);
2547 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2548 gtk_action_set_sensitive (action, rich_text && editor_focused);
2549 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2550 gtk_action_set_sensitive (action, rich_text && editor_focused);
2551 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2552 gtk_action_set_sensitive (action, rich_text && editor_focused);
2553 widget = priv->font_color_button;
2554 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2555 widget = priv->font_size_toolitem;
2556 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2557 widget = priv->font_face_toolitem;
2558 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2562 setup_insensitive_handlers (ModestMsgEditWindow *window)
2564 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2565 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2568 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2569 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2570 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2571 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2572 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2573 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2574 widget = priv->font_color_button;
2575 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2576 widget = priv->font_size_toolitem;
2577 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2578 widget = priv->font_face_toolitem;
2579 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2584 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2586 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2589 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2590 gtk_action_set_sensitive (action, can_undo);
2594 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2596 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2599 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/RedoMenu");
2600 gtk_action_set_sensitive (action, can_redo);
2604 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2607 GtkTextIter match_start, match_end;
2609 if (image_id == NULL)
2612 gtk_text_buffer_get_start_iter (buffer, &iter);
2614 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2615 GSList *tags = gtk_text_iter_get_tags (&match_start);
2617 for (node = tags; node != NULL; node = g_slist_next (node)) {
2618 GtkTextTag *tag = (GtkTextTag *) node->data;
2619 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2620 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2621 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2623 offset = gtk_text_iter_get_offset (&match_start);
2624 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2625 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2629 gtk_text_iter_forward_char (&iter);
2634 msg_body_focus (GtkWidget *focus,
2635 GdkEventFocus *event,
2639 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2644 recpt_field_changed (GtkTextBuffer *buffer,
2645 ModestMsgEditWindow *editor)
2647 update_send_dimming (editor);
2651 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2653 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2654 const gchar *subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2655 if (subject == NULL || subject[0] == '\0') {
2656 hildon_banner_show_information (NULL, NULL, _("mcen_ib_subject_or_body_not_modified"));
2658 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2663 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2665 gboolean rich_text, editor_focused;
2667 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2668 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2669 editor_focused = gtk_widget_is_focus (priv->msg_body);
2672 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2673 else if (!editor_focused)
2674 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2678 reset_modified (ModestMsgEditWindow *editor)
2680 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2681 GtkTextBuffer *buffer;
2683 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2684 gtk_text_buffer_set_modified (buffer, FALSE);
2685 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2686 gtk_text_buffer_set_modified (buffer, FALSE);
2687 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2688 gtk_text_buffer_set_modified (buffer, FALSE);
2689 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2693 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2695 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2696 GtkTextBuffer *buffer;
2698 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2699 if (gtk_text_buffer_get_modified (buffer))
2701 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2702 if (gtk_text_buffer_get_modified (buffer))
2704 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2705 if (gtk_text_buffer_get_modified (buffer))
2707 if (gtk_text_buffer_get_modified (priv->text_buffer))
2714 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
2716 ModestMsgEditWindowPrivate *priv = NULL;
2718 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2719 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2721 /* check if there's no recipient added */
2722 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2723 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2724 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2725 /* no recipient contents, then select contacts */
2726 modest_msg_edit_window_open_addressbook (window, NULL);
2730 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
2731 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2734 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
2735 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
2738 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
2739 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
2743 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
2744 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
2745 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2752 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2753 ModestMsgEditWindow *window)
2755 modest_msg_edit_window_offer_attach_file (window);
2759 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2761 ModestMsgEditWindow *window)
2763 ModestWindowPrivate *parent_priv;
2764 ModestMsgEditWindowPrivate *priv;
2766 GList *selected_attachments = NULL;
2767 gint n_att_selected = 0;
2769 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2770 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2772 if (!GTK_WIDGET_VISIBLE (window))
2775 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2776 n_att_selected = g_list_length (selected_attachments);
2777 g_list_free (selected_attachments);
2779 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2780 gtk_action_set_sensitive (action, n_att_selected == 1);
2782 update_copy_cut_dimming (window);
2783 update_paste_dimming (window);
2787 update_window_title (ModestMsgEditWindow *window)
2789 ModestMsgEditWindowPrivate *priv = NULL;
2790 const gchar *subject;
2792 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2793 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2794 if (subject == NULL || subject[0] == '\0')
2795 subject = _("mail_va_new_email");
2797 gtk_window_set_title (GTK_WINDOW (window), subject);
2802 subject_field_changed (GtkEditable *editable,
2803 ModestMsgEditWindow *window)
2805 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2806 update_window_title (window);
2807 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2808 update_send_dimming (window);
2812 subject_field_insert_text (GtkEditable *editable,
2814 gint new_text_length,
2816 ModestMsgEditWindow *window)
2818 GString *result = g_string_new ("");
2820 gint result_len = 0;
2822 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
2823 gunichar c = g_utf8_get_char_validated (current, 8);
2824 /* Invalid unichar, stop */
2830 result = g_string_append_unichar (result, c);
2834 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
2835 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
2837 g_signal_emit_by_name (editable, "insert-text",
2838 (gpointer) result->str, (gpointer) strlen (result->str),
2839 (gpointer) position, (gpointer) window);
2842 g_string_free (result, TRUE);
2846 message_is_empty (ModestMsgEditWindow *window)
2848 ModestMsgEditWindowPrivate *priv = NULL;
2850 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2851 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2853 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
2854 * so we can ignore markup.
2856 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
2859 count = gtk_text_buffer_get_char_count (buf);
2865 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2868 ModestMsgEditWindowPrivate *priv = NULL;
2870 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2871 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2873 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2876 gtk_widget_show_all (priv->find_toolbar);
2877 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2879 gtk_widget_hide_all (priv->find_toolbar);
2880 gtk_widget_grab_focus (priv->msg_body);
2886 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2888 GtkTextIter *match_start,
2889 GtkTextIter *match_end)
2891 GtkTextIter end_iter;
2892 gchar *str_casefold;
2895 gchar *range_casefold;
2898 gboolean result = FALSE;
2905 gtk_text_iter_forward_to_end (&end_iter);
2907 str_casefold = g_utf8_casefold (str, -1);
2908 str_chars_n = strlen (str);
2910 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2911 range_casefold = g_utf8_casefold (range_text, -1);
2912 range_chars_n = strlen (range_casefold);
2914 if (range_chars_n < str_chars_n) {
2915 g_free (str_casefold);
2916 g_free (range_text);
2917 g_free (range_casefold);
2921 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2922 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2923 if (!g_utf8_collate (range_subtext, str_casefold)) {
2924 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2926 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2927 match_start, match_end, NULL);
2928 g_free (found_text);
2930 g_free (range_subtext);
2934 g_free (str_casefold);
2935 g_free (range_text);
2936 g_free (range_casefold);
2943 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2944 ModestMsgEditWindow *window)
2946 gchar *current_search = NULL;
2947 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2949 GtkTextIter selection_start, selection_end;
2950 GtkTextIter match_start, match_end;
2951 gboolean continue_search = FALSE;
2953 if (message_is_empty (window)) {
2954 g_free (priv->last_search);
2955 priv->last_search = NULL;
2956 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
2960 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2961 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2962 g_free (current_search);
2963 g_free (priv->last_search);
2964 priv->last_search = NULL;
2965 /* Information banner about empty search */
2966 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2970 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2971 continue_search = TRUE;
2973 g_free (priv->last_search);
2974 priv->last_search = g_strdup (current_search);
2977 if (continue_search) {
2978 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2979 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2980 &match_start, &match_end);
2982 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2984 GtkTextIter buffer_start;
2985 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2986 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2987 &match_start, &match_end);
2989 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2992 /* Mark as selected the string found in search */
2994 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2995 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2997 g_free (priv->last_search);
2998 priv->last_search = NULL;
3000 g_free (current_search);
3004 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3005 ModestMsgEditWindow *window)
3007 GtkToggleAction *toggle;
3008 ModestWindowPrivate *parent_priv;
3009 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3011 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3012 gtk_toggle_action_set_active (toggle, FALSE);
3017 update_copy_cut_dimming (ModestMsgEditWindow *window)
3019 ModestWindowPrivate *parent_priv = NULL;
3020 ModestMsgEditWindowPrivate *priv = NULL;
3021 GtkClipboard *clipboard = NULL;
3022 GtkAction *action = NULL;
3023 gboolean has_selection = FALSE;
3024 GtkWidget *focused = NULL;
3025 gchar *selection = NULL;
3027 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3028 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3029 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3030 focused = gtk_window_get_focus (GTK_WINDOW (window));
3032 has_selection = gtk_clipboard_wait_for_targets (clipboard, NULL, NULL);
3034 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
3035 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
3036 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
3037 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
3039 if (selection != NULL)
3044 update_paste_dimming (ModestMsgEditWindow *window)
3046 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3047 GtkAction *action = NULL;
3048 GtkClipboard *clipboard = NULL;
3049 ModestEmailClipboard *e_clipboard;
3053 focused = gtk_window_get_focus (GTK_WINDOW (window));
3055 e_clipboard = modest_runtime_get_email_clipboard ();
3056 if (!modest_email_clipboard_cleared (e_clipboard)) {
3059 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3060 active = gtk_clipboard_wait_is_text_available (clipboard);
3064 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
3068 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
3069 gtk_action_set_sensitive (action, active);
3074 update_select_all_dimming (ModestMsgEditWindow *window)
3077 gboolean dimmed = FALSE;
3079 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3081 focused = gtk_window_get_focus (GTK_WINDOW (window));
3082 if (GTK_IS_ENTRY (focused)) {
3083 const gchar *current_text;
3084 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
3085 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
3086 } else if (GTK_IS_TEXT_VIEW (focused)) {
3087 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
3088 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
3089 } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
3092 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
3093 gtk_action_set_sensitive (action, !dimmed);
3097 update_zoom_dimming (ModestMsgEditWindow *window)
3100 gboolean dimmed = FALSE;
3102 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3104 focused = gtk_window_get_focus (GTK_WINDOW (window));
3105 dimmed = ! WP_IS_TEXT_VIEW (focused);
3106 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
3107 gtk_action_set_sensitive (action, !dimmed);
3111 update_send_dimming (ModestMsgEditWindow *window)
3113 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3114 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3115 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
3116 const gchar *subject;
3117 gboolean dim = FALSE;
3120 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
3121 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
3122 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
3123 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3125 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
3126 gtk_text_buffer_get_char_count (cc_buffer) +
3127 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
3129 dim = dim || (subject == NULL || subject[0] == '\0');
3131 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
3132 gtk_action_set_sensitive (action, !dim);
3133 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
3134 gtk_action_set_sensitive (action, !dim);
3138 edit_menu_activated (GtkAction *action,
3141 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3143 update_select_all_dimming (window);
3144 update_copy_cut_dimming (window);
3145 update_paste_dimming (window);
3148 view_menu_activated (GtkAction *action,
3151 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3153 update_zoom_dimming (window);
3157 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3159 ModestMsgEditWindowPrivate *priv;
3161 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3166 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3169 ModestMsgEditWindowPrivate *priv;
3171 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3177 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3180 ModestMsgEditWindowPrivate *priv;
3181 TnyHeader *header = NULL;
3183 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3184 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3186 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3187 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3189 if (priv->draft_msg != NULL) {
3190 header = tny_msg_get_header (priv->draft_msg);
3191 if (TNY_IS_HEADER (header)) {
3192 modest_window_mgr_unregister_header (mgr, header);
3194 g_object_unref (priv->draft_msg);
3197 if (draft != NULL) {
3198 g_object_ref (draft);
3199 header = tny_msg_get_header (draft);
3200 if (TNY_IS_HEADER (header))
3201 modest_window_mgr_register_header (mgr, header);
3202 if (priv->msg_uid) {
3203 g_free (priv->msg_uid);
3204 priv->msg_uid = NULL;
3206 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3209 priv->draft_msg = draft;
3213 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3214 GtkTextIter *start, GtkTextIter *end,
3217 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3218 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3221 if (tag == NULL+13) return;
3222 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3223 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3224 replace_with_attachments (window, priv->attachments);
3229 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3232 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3234 g_return_if_fail (TNY_IS_MIME_PART (part));
3235 priv->attachments = g_list_prepend (priv->attachments, part);
3236 g_object_ref (part);
3237 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part);
3238 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3239 gtk_widget_show_all (priv->attachments_caption);
3240 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3244 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3246 ModestMsgEditWindowPrivate *priv;
3248 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3249 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3251 return priv->msg_uid;