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_select_all_dimming (ModestMsgEditWindow *window);
142 static void update_zoom_dimming (ModestMsgEditWindow *window);
145 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
146 ModestMsgEditWindow *window);
147 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
148 ModestMsgEditWindow *window);
149 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
151 GtkTextIter *match_start,
152 GtkTextIter *match_end);
154 static void DEBUG_BUFFER (WPTextBuffer *buffer)
159 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
160 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
161 while (!gtk_text_iter_is_end (&iter)) {
162 GString *output = g_string_new ("");
163 GSList *toggled_tags;
166 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
167 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
168 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
169 GtkTextTag *tag = (GtkTextTag *) node->data;
171 g_object_get (G_OBJECT (tag), "name", &name, NULL);
172 output = g_string_append (output, name);
173 g_string_append (output, " ");
175 output = g_string_append (output, "] OPENED [ ");
176 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
177 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
178 GtkTextTag *tag = (GtkTextTag *) node->data;
180 g_object_get (G_OBJECT (tag), "name", &name, NULL);
181 output = g_string_append (output, name);
182 g_string_append (output, " ");
184 output = g_string_append (output, "]\n");
185 g_message ("%s", output->str);
186 g_string_free (output, TRUE);
187 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
189 g_message ("END BUFFER");
194 /* static gboolean */
195 /* on_key_pressed (GtkWidget *self, */
196 /* GdkEventKey *event, */
197 /* gpointer user_data); */
199 static void edit_menu_activated (GtkAction *action,
201 static void view_menu_activated (GtkAction *action,
204 /* list my signals */
211 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
212 struct _ModestMsgEditWindowPrivate {
214 GtkWidget *header_box;
216 ModestPairList *from_field_protos;
217 GtkWidget *from_field;
221 GtkWidget *bcc_field;
222 GtkWidget *subject_field;
223 GtkWidget *attachments_view;
224 GtkWidget *priority_icon;
225 GtkWidget *add_attachment_button;
227 GtkWidget *cc_caption;
228 GtkWidget *bcc_caption;
229 gboolean update_caption_visibility;
230 GtkWidget *attachments_caption;
232 GtkTextBuffer *text_buffer;
234 GtkWidget *font_size_toolitem;
235 GtkWidget *font_face_toolitem;
236 GtkWidget *font_color_button;
237 GSList *font_items_group;
238 GtkWidget *font_tool_button_label;
239 GSList *size_items_group;
240 GtkWidget *size_tool_button_label;
242 GtkWidget *find_toolbar;
246 GtkWidget *scroll_area;
247 gint last_vadj_upper;
252 TnyHeaderFlags priority_flags;
256 gulong clipboard_change_handler_id;
265 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
266 MODEST_TYPE_MSG_EDIT_WINDOW, \
267 ModestMsgEditWindowPrivate))
269 static GtkWindowClass *parent_class = NULL;
271 /* uncomment the following if you have defined any signals */
272 /* static guint signals[LAST_SIGNAL] = {0}; */
275 modest_msg_edit_window_get_type (void)
277 static GType my_type = 0;
279 static const GTypeInfo my_info = {
280 sizeof(ModestMsgEditWindowClass),
281 NULL, /* base init */
282 NULL, /* base finalize */
283 (GClassInitFunc) modest_msg_edit_window_class_init,
284 NULL, /* class finalize */
285 NULL, /* class data */
286 sizeof(ModestMsgEditWindow),
288 (GInstanceInitFunc) modest_msg_edit_window_init,
291 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
292 "ModestMsgEditWindow",
295 wp_text_buffer_library_init ();
301 save_state (ModestWindow *self)
303 modest_widget_memory_save (modest_runtime_get_conf(),
304 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
309 restore_settings (ModestMsgEditWindow *self)
311 modest_widget_memory_restore (modest_runtime_get_conf(),
312 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
317 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
319 GObjectClass *gobject_class;
320 ModestWindowClass *modest_window_class;
321 gobject_class = (GObjectClass*) klass;
322 modest_window_class = (ModestWindowClass*) klass;
324 parent_class = g_type_class_peek_parent (klass);
325 gobject_class->finalize = modest_msg_edit_window_finalize;
327 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
328 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
329 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
330 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
331 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
332 modest_window_class->save_state_func = save_state;
333 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
335 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
339 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
341 ModestMsgEditWindowPrivate *priv;
342 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
344 priv->msg_body = NULL;
345 priv->from_field = NULL;
346 priv->to_field = NULL;
347 priv->cc_field = NULL;
348 priv->bcc_field = NULL;
349 priv->subject_field = NULL;
350 priv->attachments = NULL;
352 priv->zoom_level = 1.0;
354 priv->cc_caption = NULL;
355 priv->bcc_caption = NULL;
356 priv->update_caption_visibility = FALSE;
358 priv->priority_flags = 0;
360 priv->find_toolbar = NULL;
361 priv->last_search = NULL;
363 priv->draft_msg = NULL;
364 priv->outbox_msg = NULL;
365 priv->msg_uid = NULL;
366 priv->clipboard_change_handler_id = 0;
369 priv->last_vadj_upper = 0;
373 /* FIXME: this is a dup from the one in gtk/ */
376 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
378 static ModestPairList*
379 get_transports (void)
381 GSList *transports = NULL;
383 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
384 GSList *accounts = modest_account_mgr_account_names (account_mgr,
385 TRUE /* only enabled accounts. */);
387 GSList *cursor = accounts;
389 gchar *account_name = cursor->data;
390 gchar *from_string = NULL;
392 from_string = modest_account_mgr_get_from_string (account_mgr,
396 if (from_string && account_name) {
397 gchar *name = account_name;
398 ModestPair *pair = modest_pair_new ((gpointer) name,
399 (gpointer) from_string , TRUE);
400 transports = g_slist_prepend (transports, pair);
403 cursor = cursor->next;
405 g_slist_free (accounts); /* only free the accounts, not the elements,
406 * because they are used in the pairlist */
410 void vadj_changed (GtkAdjustment *adj,
411 ModestMsgEditWindow *window)
413 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
415 GdkRectangle rectangle, cursor_rectangle;
416 GtkTextIter position;
420 /* We detect if cursor is visible using the full height, not only the center. This
422 gtk_text_view_get_visible_rect (GTK_TEXT_VIEW (priv->msg_body), &rectangle);
423 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer),
425 gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer)));
426 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &position, &cursor_rectangle);
428 cursor_bottom = (cursor_rectangle.y + cursor_rectangle.height);
429 visible = (cursor_rectangle.y >= rectangle.y) && (cursor_bottom < (rectangle.y + rectangle.height));
431 if (gtk_widget_is_focus (priv->msg_body) &&
433 if (priv->last_vadj_upper != adj->upper) {
436 insert = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
437 gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (priv->msg_body),
438 insert, 0.1, FALSE, 0.0, 0.0);
441 priv->last_vadj_upper = adj->upper;
446 init_window (ModestMsgEditWindow *obj)
448 GtkWidget *from_caption, *to_caption, *subject_caption;
449 GtkWidget *main_vbox;
450 ModestMsgEditWindowPrivate *priv;
452 GtkSizeGroup *size_group;
454 GtkWidget *subject_box;
455 GtkWidget *attachment_icon;
456 GtkWidget *window_box;
457 #if (GTK_MINOR_VERSION >= 10)
458 GdkAtom deserialize_type;
460 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
462 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
464 /* Note: This ModestPairList* must exist for as long as the combo
465 * that uses it, because the ModestComboBox uses the ID opaquely,
466 * so it can't know how to manage its memory. */
467 priv->from_field_protos = get_transports ();
469 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
471 priv->to_field = modest_recpt_editor_new ();
472 priv->cc_field = modest_recpt_editor_new ();
473 priv->bcc_field = modest_recpt_editor_new ();
474 subject_box = gtk_hbox_new (FALSE, 0);
475 priv->priority_icon = gtk_image_new ();
476 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
477 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
478 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
479 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
480 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
481 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
482 priv->add_attachment_button = gtk_button_new ();
483 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
484 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
485 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
486 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
487 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
488 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
489 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
490 priv->attachments_view = modest_attachments_view_new (NULL);
492 priv->header_box = gtk_vbox_new (FALSE, 0);
494 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
495 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
496 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
497 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
498 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
499 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
500 g_object_unref (size_group);
502 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
503 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
504 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
505 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
506 gtk_size_group_add_widget (size_group, priv->subject_field);
507 gtk_size_group_add_widget (size_group, priv->attachments_view);
508 g_object_unref (size_group);
510 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
511 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
512 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
513 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
514 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
515 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
516 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
519 priv->msg_body = wp_text_view_new ();
520 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
521 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
522 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
523 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
524 #if (GTK_MINOR_VERSION >= 10)
525 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
526 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
528 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
529 deserialize_type, TRUE);
531 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
533 priv->find_toolbar = hildon_find_toolbar_new (NULL);
534 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
536 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
538 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
539 G_CALLBACK (text_buffer_refresh_attributes), obj);
540 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
541 G_CALLBACK (text_buffer_can_undo), obj);
542 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
543 G_CALLBACK (text_buffer_can_redo), obj);
544 g_signal_connect (G_OBJECT (obj), "window-state-event",
545 G_CALLBACK (modest_msg_edit_window_window_state_event),
547 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
548 G_CALLBACK (text_buffer_apply_tag), obj);
549 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
550 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
551 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
552 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
553 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
554 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
556 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
557 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
559 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
560 G_CALLBACK (msg_body_focus), obj);
561 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
562 G_CALLBACK (msg_body_focus), obj);
563 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
564 "changed", G_CALLBACK (recpt_field_changed), obj);
565 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
566 "changed", G_CALLBACK (recpt_field_changed), obj);
567 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
568 "changed", G_CALLBACK (recpt_field_changed), obj);
569 recpt_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
570 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
571 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
573 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
574 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
576 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
577 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
578 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
579 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
581 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
583 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
584 frame = gtk_frame_new (NULL);
585 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
587 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
588 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
589 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
591 G_CALLBACK (vadj_changed),
593 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
595 window_box = gtk_vbox_new (FALSE, 0);
596 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
597 gtk_container_add (GTK_CONTAINER(obj), window_box);
598 priv->scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
599 gtk_container_add (GTK_CONTAINER (frame), priv->scroll_area);
601 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
602 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
607 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
609 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
611 if (g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
612 priv->clipboard_change_handler_id))
613 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
614 priv->clipboard_change_handler_id);
618 modest_msg_edit_window_finalize (GObject *obj)
620 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
622 /* Sanity check: shouldn't be needed, the window mgr should
623 call this function before */
624 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
626 if (priv->draft_msg != NULL) {
627 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
628 if (TNY_IS_HEADER (header)) {
629 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
630 modest_window_mgr_unregister_header (mgr, header);
632 g_object_unref (priv->draft_msg);
633 priv->draft_msg = NULL;
635 if (priv->outbox_msg != NULL) {
636 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
637 if (TNY_IS_HEADER (header)) {
638 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
639 modest_window_mgr_unregister_header (mgr, header);
641 g_object_unref (priv->outbox_msg);
642 priv->outbox_msg = NULL;
644 if (priv->msg_uid != NULL) {
645 g_free (priv->msg_uid);
646 priv->msg_uid = NULL;
649 /* This had to stay alive for as long as the combobox that used it: */
650 modest_pair_list_free (priv->from_field_protos);
652 G_OBJECT_CLASS(parent_class)->finalize (obj);
656 menubar_to_menu (GtkUIManager *ui_manager)
658 GtkWidget *main_menu;
662 /* Create new main menu */
663 main_menu = gtk_menu_new();
665 /* Get the menubar from the UI manager */
666 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
668 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
672 menu = GTK_WIDGET (iter->data);
673 gtk_widget_reparent(menu, main_menu);
675 iter = g_list_next (iter);
681 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type)
683 GdkPixbufLoader *loader;
686 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
691 tny_stream_reset (TNY_STREAM (stream));
692 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
693 unsigned char read_buffer[128];
695 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
696 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
700 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
701 g_object_ref (pixbuf);
702 gdk_pixbuf_loader_close (loader, NULL);
703 g_object_unref (loader);
705 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
706 GdkPixbuf *new_pixbuf;
708 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
709 gdk_pixbuf_get_width (pixbuf);
710 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
711 g_object_unref (pixbuf);
719 replace_with_attachments (ModestMsgEditWindow *self, GList *attachments)
721 ModestMsgEditWindowPrivate *priv;
724 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
726 for (node = attachments; node != NULL; node = g_list_next (node)) {
727 TnyMimePart *part = (TnyMimePart *) node->data;
728 const gchar *cid = tny_mime_part_get_content_id (part);
729 const gchar *mime_type = tny_mime_part_get_content_type (part);
730 if ((cid != NULL)&&(mime_type != NULL)) {
731 TnyStream *stream = tny_mime_part_get_stream (part);
732 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type);
733 g_object_unref (stream);
735 if (pixbuf != NULL) {
736 /* wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf); */
737 g_object_unref (pixbuf);
744 update_last_cid (ModestMsgEditWindow *self, GList *attachments)
747 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
749 for (node = attachments; node != NULL; node = g_list_next (node)) {
750 TnyMimePart *part = (TnyMimePart *) node->data;
751 const gchar *cid = tny_mime_part_get_content_id (part);
753 char *invalid = NULL;
754 gint int_cid = strtol (cid, &invalid, 10);
755 if ((invalid != NULL) && (*invalid == '\0') && (int_cid > priv->last_cid)) {
756 priv->last_cid = int_cid;
764 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
767 const gchar *to, *cc, *bcc, *subject;
769 ModestMsgEditWindowPrivate *priv;
771 TnyHeaderFlags priority_flags;
772 TnyFolder *msg_folder;
773 gboolean is_html = FALSE;
775 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
776 g_return_if_fail (TNY_IS_MSG (msg));
778 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
780 header = tny_msg_get_header (msg);
781 to = tny_header_get_to (header);
782 cc = tny_header_get_cc (header);
783 bcc = tny_header_get_bcc (header);
784 subject = tny_header_get_subject (header);
785 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
788 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
790 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
791 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
792 gtk_widget_show (priv->cc_caption);
793 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
794 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
795 gtk_widget_hide (priv->cc_caption);
798 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
799 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
800 gtk_widget_show (priv->bcc_caption);
801 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
802 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
803 gtk_widget_hide (priv->bcc_caption);
806 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
807 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
810 update_window_title (self);
812 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
813 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
815 if ((body == NULL)||(body[0] == '\0')) {
817 body = modest_text_utils_convert_to_html ("");
820 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
821 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
824 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
827 if (preserve_is_rich && !is_html) {
828 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
829 /* Get the default format required from configuration */
830 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
831 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
834 /* Set the default focus depending on having already a To: field or not */
835 if ((!to)||(*to == '\0')) {
836 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
838 gtk_widget_grab_focus (priv->msg_body);
841 /* TODO: lower priority, select in the From: combo to the
842 value that comes from msg <- not sure, should it be
845 /* Add attachments to the view */
846 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
847 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
848 if (priv->attachments == NULL) {
849 gtk_widget_hide (priv->attachments_caption);
851 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
852 gtk_widget_show_all (priv->attachments_caption);
853 replace_with_attachments (self, priv->attachments);
855 update_last_cid (self, priv->attachments);
857 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
859 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
860 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
862 reset_modified (self);
864 update_dimmed (self);
865 text_buffer_can_undo (priv->text_buffer, FALSE, self);
866 text_buffer_can_redo (priv->text_buffer, FALSE, self);
869 g_free (priv->msg_uid);
870 priv->msg_uid = NULL;
873 /* we should set a reference to the incoming message if it is a draft */
874 msg_folder = tny_msg_get_folder (msg);
876 if (modest_tny_folder_is_local_folder (msg_folder)) {
877 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
878 if (type == TNY_FOLDER_TYPE_DRAFTS)
879 priv->draft_msg = g_object_ref(msg);
880 if (type == TNY_FOLDER_TYPE_OUTBOX)
881 priv->outbox_msg = g_object_ref(msg);
882 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
884 g_object_unref (msg_folder);
889 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
892 GList *item_children, *node;
893 GtkWidget *bin_child;
895 bin_child = gtk_bin_get_child (GTK_BIN(item));
897 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
899 for (node = item_children; node != NULL; node = g_list_next (node)) {
900 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
901 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
904 g_list_free (item_children);
908 menu_tool_button_dont_expand (GtkMenuToolButton *item)
911 GList *item_children, *node;
913 box = gtk_bin_get_child (GTK_BIN (item));
914 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
915 item_children = gtk_container_get_children (GTK_CONTAINER (box));
917 for (node = item_children; node != NULL; node = g_list_next (node)) {
918 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
919 if (GTK_IS_TOGGLE_BUTTON (node->data))
920 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
921 else if (GTK_IS_BUTTON (node->data))
922 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
924 g_list_free (item_children);
929 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
931 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
932 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
933 GtkWidget *placeholder;
934 GtkWidget *tool_item;
939 GtkWidget *sizes_menu;
940 GtkWidget *fonts_menu;
941 GSList *radio_group = NULL;
946 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
947 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
949 /* should we hide the toolbar? */
950 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
951 gtk_widget_hide (parent_priv->toolbar);
953 /* Font color placeholder */
954 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
955 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
958 tool_item = GTK_WIDGET (gtk_tool_item_new ());
959 priv->font_color_button = hildon_color_button_new ();
960 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
961 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
962 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
963 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
964 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
965 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
966 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
968 /* Font size and face placeholder */
969 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
970 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
972 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
973 priv->size_tool_button_label = gtk_label_new (NULL);
974 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
975 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
976 size_text,"</span>", NULL);
977 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
979 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
980 sizes_menu = gtk_menu_new ();
981 priv->size_items_group = NULL;
983 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
984 GtkWidget *size_menu_item;
986 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
987 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
988 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
989 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
990 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
991 gtk_widget_show (size_menu_item);
993 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
997 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
998 GtkWidget *item = (GtkWidget *) node->data;
999 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1003 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1004 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1005 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1006 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1007 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1008 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1009 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1010 priv->font_size_toolitem = tool_item;
1013 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1014 priv->font_tool_button_label = gtk_label_new (NULL);
1015 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1016 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1018 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1019 fonts_menu = gtk_menu_new ();
1020 priv->font_items_group = NULL;
1022 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1023 GtkWidget *font_menu_item;
1024 GtkWidget *child_label;
1026 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1027 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1028 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1029 wp_get_font_name (font_index), "</span>", NULL);
1030 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1033 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1034 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1035 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1036 gtk_widget_show (font_menu_item);
1038 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1041 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1042 GtkWidget *item = (GtkWidget *) node->data;
1043 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1046 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1047 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1048 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1049 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1050 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1051 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1052 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1053 priv->font_face_toolitem = tool_item;
1055 /* Set expand and homogeneous for remaining items */
1056 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1057 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1058 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1059 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1060 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1061 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1062 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1063 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1064 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1072 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1075 ModestWindowPrivate *parent_priv;
1076 ModestMsgEditWindowPrivate *priv;
1077 GtkActionGroup *action_group;
1078 GError *error = NULL;
1079 GdkPixbuf *window_icon = NULL;
1082 gboolean prefer_formatted;
1084 ModestPair *account_pair = NULL;
1086 g_return_val_if_fail (msg, NULL);
1087 g_return_val_if_fail (account_name, NULL);
1089 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
1091 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1092 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1094 parent_priv->ui_manager = gtk_ui_manager_new();
1095 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
1096 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1098 /* Add common actions */
1099 gtk_action_group_add_actions (action_group,
1100 modest_msg_edit_action_entries,
1101 G_N_ELEMENTS (modest_msg_edit_action_entries),
1103 gtk_action_group_add_toggle_actions (action_group,
1104 modest_msg_edit_toggle_action_entries,
1105 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
1107 gtk_action_group_add_radio_actions (action_group,
1108 modest_msg_edit_alignment_radio_action_entries,
1109 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
1111 G_CALLBACK (modest_ui_actions_on_change_justify),
1113 gtk_action_group_add_radio_actions (action_group,
1114 modest_msg_edit_zoom_action_entries,
1115 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
1117 G_CALLBACK (modest_ui_actions_on_change_zoom),
1119 gtk_action_group_add_radio_actions (action_group,
1120 modest_msg_edit_priority_action_entries,
1121 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
1123 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
1125 gtk_action_group_add_radio_actions (action_group,
1126 modest_msg_edit_file_format_action_entries,
1127 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
1128 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
1129 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
1131 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1132 g_object_unref (action_group);
1134 /* Load the UI definition */
1135 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
1137 if (error != NULL) {
1138 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
1139 g_clear_error (&error);
1142 /* Add accelerators */
1143 gtk_window_add_accel_group (GTK_WINDOW (obj),
1144 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1147 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
1148 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1151 init_window (MODEST_MSG_EDIT_WINDOW(obj));
1153 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1155 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1157 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1158 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1160 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
1162 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
1163 if (account_pair != NULL)
1164 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
1166 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1168 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1170 /* Set window icon */
1171 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
1173 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1174 g_object_unref (window_icon);
1177 /* Dim at start clipboard actions */
1178 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
1179 gtk_action_set_sensitive (action, FALSE);
1180 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
1181 gtk_action_set_sensitive (action, FALSE);
1182 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
1183 gtk_action_set_sensitive (action, FALSE);
1185 /* Update select all */
1186 update_select_all_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1187 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu");
1188 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (edit_menu_activated), obj);
1189 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu");
1190 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (view_menu_activated), obj);
1192 /* set initial state of cc and bcc */
1193 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
1194 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1195 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
1196 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
1197 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1198 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
1200 /* Setup the file format */
1201 conf = modest_runtime_get_conf ();
1202 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
1204 g_clear_error (&error);
1205 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
1207 file_format = (prefer_formatted) ?
1208 MODEST_FILE_FORMAT_FORMATTED_TEXT :
1209 MODEST_FILE_FORMAT_PLAIN_TEXT;
1210 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
1212 update_paste_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1213 priv->update_caption_visibility = TRUE;
1215 reset_modified (MODEST_MSG_EDIT_WINDOW (obj));
1217 return (ModestWindow*) obj;
1221 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1223 GString **string_buffer = (GString **) user_data;
1225 *string_buffer = g_string_append (*string_buffer, buffer);
1231 * @result: A new string which should be freed with g_free().
1234 get_formatted_data (ModestMsgEditWindow *edit_window)
1236 ModestMsgEditWindowPrivate *priv;
1237 GString *string_buffer = g_string_new ("");
1239 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1241 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1243 return g_string_free (string_buffer, FALSE);
1248 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1251 const gchar *account_name;
1252 ModestMsgEditWindowPrivate *priv;
1254 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1256 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1258 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1259 g_return_val_if_fail (account_name, NULL);
1262 /* don't free these (except from) */
1263 data = g_slice_new0 (MsgData);
1264 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1266 data->account_name = g_strdup (account_name);
1267 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1268 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1269 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1270 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1271 if (priv->draft_msg) {
1272 data->draft_msg = g_object_ref (priv->draft_msg);
1274 if (priv->outbox_msg) {
1275 data->draft_msg = g_object_ref (priv->outbox_msg);
1277 data->draft_msg = NULL;
1280 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1282 gtk_text_buffer_get_bounds (buf, &b, &e);
1283 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1285 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1286 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1288 data->html_body = NULL;
1290 /* deep-copy the data */
1291 GList *cursor = priv->attachments;
1292 data->attachments = NULL;
1294 if (!(TNY_IS_MIME_PART(cursor->data))) {
1295 g_warning ("strange data in attachment list");
1296 cursor = g_list_next (cursor);
1299 data->attachments = g_list_append (data->attachments,
1300 g_object_ref (cursor->data));
1301 cursor = g_list_next (cursor);
1304 data->priority_flags = priv->priority_flags;
1311 unref_gobject (GObject *obj, gpointer data)
1313 if (!G_IS_OBJECT(obj))
1315 g_object_unref (obj);
1319 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1322 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1330 g_free (data->subject);
1331 g_free (data->plain_body);
1332 g_free (data->html_body);
1333 g_free (data->account_name);
1335 if (data->draft_msg != NULL) {
1336 g_object_unref (data->draft_msg);
1337 data->draft_msg = NULL;
1340 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1341 g_list_free (data->attachments);
1343 g_slice_free (MsgData, data);
1347 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1350 ModestMsgEditWindowPrivate *priv = NULL;
1351 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1353 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1355 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1357 return MODEST_MSG_EDIT_FORMAT_HTML;
1359 return MODEST_MSG_EDIT_FORMAT_TEXT;
1363 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1364 ModestMsgEditFormat format)
1366 ModestMsgEditWindowPrivate *priv;
1368 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1369 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1372 case MODEST_MSG_EDIT_FORMAT_HTML:
1373 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1375 case MODEST_MSG_EDIT_FORMAT_TEXT:
1376 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1379 g_return_if_reached ();
1383 ModestMsgEditFormatState *
1384 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1386 ModestMsgEditFormatState *format_state = NULL;
1387 ModestMsgEditWindowPrivate *priv;
1388 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1390 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1391 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1393 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1395 format_state = g_new0 (ModestMsgEditFormatState, 1);
1396 format_state->bold = buffer_format->bold&0x1;
1397 format_state->italics = buffer_format->italic&0x1;
1398 format_state->bullet = buffer_format->bullet&0x1;
1399 format_state->color = buffer_format->color;
1400 format_state->font_size = buffer_format->font_size;
1401 format_state->font_family = wp_get_font_name (buffer_format->font);
1402 format_state->justification = buffer_format->justification;
1403 g_free (buffer_format);
1405 return format_state;
1410 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1411 const ModestMsgEditFormatState *format_state)
1413 ModestMsgEditWindowPrivate *priv;
1414 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1415 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1416 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1417 g_return_if_fail (format_state != NULL);
1419 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1420 gtk_widget_grab_focus (priv->msg_body);
1421 buffer_format->bold = (format_state->bold != FALSE);
1422 buffer_format->italic = (format_state->italics != FALSE);
1423 buffer_format->color = format_state->color;
1424 buffer_format->font_size = format_state->font_size;
1425 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1426 buffer_format->justification = format_state->justification;
1427 buffer_format->bullet = format_state->bullet;
1429 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1431 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1432 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1433 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1434 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1435 buffer_format->cs.font = (buffer_format->font != current_format->font);
1436 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1437 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1439 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1440 if (buffer_format->cs.bold) {
1441 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1443 if (buffer_format->cs.italic) {
1444 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1446 if (buffer_format->cs.color) {
1447 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1449 if (buffer_format->cs.font_size) {
1450 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1452 if (buffer_format->cs.justification) {
1453 switch (buffer_format->justification) {
1454 case GTK_JUSTIFY_LEFT:
1455 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1457 case GTK_JUSTIFY_CENTER:
1458 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1460 case GTK_JUSTIFY_RIGHT:
1461 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1468 if (buffer_format->cs.font) {
1469 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1471 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1472 if (buffer_format->cs.bullet) {
1473 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((buffer_format->bullet)?1:0));
1475 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1477 g_free (current_format);
1482 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1484 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1486 ModestWindowPrivate *parent_priv;
1487 ModestMsgEditWindowPrivate *priv;
1488 GtkWidget *new_size_menuitem;
1489 GtkWidget *new_font_menuitem;
1491 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1492 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1494 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1495 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1496 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1497 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1499 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1500 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1501 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1504 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1506 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1507 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1509 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1510 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1512 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1513 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1515 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1516 G_CALLBACK (modest_msg_edit_window_color_button_change),
1518 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1519 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1520 G_CALLBACK (modest_msg_edit_window_color_button_change),
1523 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1524 buffer_format->font_size))->data);
1525 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1529 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1530 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1531 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1533 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1534 G_CALLBACK (modest_msg_edit_window_size_change),
1536 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1537 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1538 G_CALLBACK (modest_msg_edit_window_size_change),
1542 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1543 buffer_format->font))->data);
1544 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1548 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1549 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1550 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1552 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1553 G_CALLBACK (modest_msg_edit_window_font_change),
1555 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1556 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1557 G_CALLBACK (modest_msg_edit_window_font_change),
1561 g_free (buffer_format);
1567 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1570 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1571 ModestMsgEditWindowPrivate *priv;
1572 GtkWidget *dialog = NULL;
1574 const GdkColor *new_color = NULL;
1576 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1577 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1579 #ifdef MODEST_HILDON_VERSION_0
1580 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1581 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1583 dialog = hildon_color_chooser_new ();
1584 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1585 #endif /*MODEST_HILDON_VERSION_0*/
1586 g_free (buffer_format);
1588 response = gtk_dialog_run (GTK_DIALOG (dialog));
1590 case GTK_RESPONSE_OK: {
1591 #ifdef MODEST_HILDON_VERSION_0
1592 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1595 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1597 #endif /*MODEST_HILDON_VERSION_0*/
1604 gtk_widget_destroy (dialog);
1606 if (new_color != NULL)
1607 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1612 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1615 ModestMsgEditWindowPrivate *priv;
1616 GtkWidget *dialog = NULL;
1618 GdkColor *old_color = NULL;
1619 const GdkColor *new_color = NULL;
1621 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1622 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1624 #ifdef MODEST_HILDON_VERSION_0
1625 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1626 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1628 dialog = hildon_color_chooser_new ();
1629 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1630 #endif /*MODEST_HILDON_VERSION_9*/
1632 response = gtk_dialog_run (GTK_DIALOG (dialog));
1634 case GTK_RESPONSE_OK: {
1635 #ifdef MODEST_HILDON_VERSION_0
1636 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1639 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1641 #endif /*MODEST_HILDON_VERSION_0*/
1647 gtk_widget_destroy (dialog);
1649 if (new_color != NULL)
1650 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1654 static TnyStream* create_stream_for_uri (const gchar* uri)
1659 TnyStream *result = NULL;
1661 GnomeVFSHandle *handle = NULL;
1662 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1663 if (test == GNOME_VFS_OK) {
1664 /* Create the tinymail stream: */
1665 /* Presumably tinymai will call gnome_vfs_close (handle) later. */
1666 result = TNY_STREAM (tny_vfs_stream_new (handle));
1673 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1676 ModestMsgEditWindowPrivate *priv;
1677 GtkWidget *dialog = NULL;
1679 GSList *uris = NULL;
1680 GSList *uri_node = NULL;
1682 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1684 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1685 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1686 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1688 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1690 response = gtk_dialog_run (GTK_DIALOG (dialog));
1692 case GTK_RESPONSE_OK:
1693 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1698 gtk_widget_destroy (dialog);
1700 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1702 GnomeVFSHandle *handle = NULL;
1703 GnomeVFSResult result;
1704 GtkTextIter position;
1705 GtkTextMark *insert_mark;
1707 uri = (const gchar *) uri_node->data;
1708 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1709 if (result == GNOME_VFS_OK) {
1711 GnomeVFSFileInfo info;
1712 gchar *filename, *basename, *escaped_filename;
1713 TnyMimePart *mime_part;
1715 const gchar *mime_type = NULL;
1716 GnomeVFSURI *vfs_uri;
1718 vfs_uri = gnome_vfs_uri_new (uri);
1720 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1721 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1722 g_free (escaped_filename);
1723 gnome_vfs_uri_unref (vfs_uri);
1725 if (gnome_vfs_get_file_info (uri, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
1726 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1728 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1730 mime_part = tny_platform_factory_new_mime_part
1731 (modest_runtime_get_platform_factory ());
1733 TnyStream *stream = create_stream_for_uri (uri);
1734 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1736 content_id = g_strdup_printf ("%d", priv->last_cid);
1737 tny_mime_part_set_content_id (mime_part, content_id);
1738 g_free (content_id);
1741 basename = g_path_get_basename (filename);
1742 tny_mime_part_set_filename (mime_part, basename);
1745 pixbuf = pixbuf_from_stream (stream, mime_type);
1747 if (pixbuf != NULL) {
1748 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1749 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1750 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1753 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1754 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1756 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1757 gtk_widget_show_all (priv->attachments_caption);
1758 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1768 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
1771 ModestMsgEditWindowPrivate *priv;
1772 GtkWidget *dialog = NULL;
1774 GSList *uris = NULL;
1777 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1779 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1780 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
1781 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1783 response = gtk_dialog_run (GTK_DIALOG (dialog));
1785 case GTK_RESPONSE_OK:
1786 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1791 gtk_widget_destroy (dialog);
1793 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1794 const gchar *uri = (const gchar *) uri_node->data;
1795 modest_msg_edit_window_attach_file_one (window, uri);
1797 g_slist_foreach (uris, (GFunc) g_free, NULL);
1798 g_slist_free (uris);
1802 modest_msg_edit_window_attach_file_one (
1803 ModestMsgEditWindow *window,
1806 g_return_if_fail (window);
1807 g_return_if_fail (uri);
1809 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1812 GnomeVFSHandle *handle = NULL;
1813 GnomeVFSResult result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1814 if (result == GNOME_VFS_OK) {
1815 TnyMimePart *mime_part;
1817 const gchar *mime_type = NULL;
1819 gchar *escaped_filename;
1822 GnomeVFSFileInfo info;
1823 GnomeVFSURI *vfs_uri;
1825 vfs_uri = gnome_vfs_uri_new (uri);
1828 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1829 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1830 g_free (escaped_filename);
1831 gnome_vfs_uri_unref (vfs_uri);
1833 if (gnome_vfs_get_file_info (uri,
1835 GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
1836 GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1838 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1839 mime_part = tny_platform_factory_new_mime_part
1840 (modest_runtime_get_platform_factory ());
1841 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1843 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1845 content_id = g_strdup_printf ("%d", priv->last_cid);
1846 tny_mime_part_set_content_id (mime_part, content_id);
1847 g_free (content_id);
1850 basename = g_path_get_basename (filename);
1851 tny_mime_part_set_filename (mime_part, basename);
1854 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1855 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1857 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1858 gtk_widget_show_all (priv->attachments_caption);
1859 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1865 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1868 ModestMsgEditWindowPrivate *priv;
1869 gboolean clean_list = FALSE;
1871 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1872 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1874 if (att_list == NULL) {
1875 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1879 if (att_list == NULL) {
1880 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1882 GtkWidget *confirmation_dialog = NULL;
1883 gboolean dialog_response;
1885 gchar *message = NULL;
1886 const gchar *filename = NULL;
1888 if (att_list->next == NULL) {
1889 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1893 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1894 att_list->next == NULL), filename);
1895 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1897 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1898 gtk_widget_destroy (confirmation_dialog);
1899 if (!dialog_response) {
1901 g_list_free (att_list);
1904 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1906 for (node = att_list; node != NULL; node = g_list_next (node)) {
1907 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1908 const gchar *att_id;
1909 priv->attachments = g_list_remove (priv->attachments, mime_part);
1911 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1913 if (priv->attachments == NULL)
1914 gtk_widget_hide (priv->attachments_caption);
1915 att_id = tny_mime_part_get_content_id (mime_part);
1917 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1919 g_object_unref (mime_part);
1920 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1925 g_list_free (att_list);
1929 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1932 ModestMsgEditWindowPrivate *priv;
1933 GdkColor *new_color;
1934 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1936 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1937 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1940 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1942 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1944 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1946 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1951 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1954 ModestMsgEditWindowPrivate *priv;
1955 gint new_size_index;
1956 ModestMsgEditWindow *window;
1959 window = MODEST_MSG_EDIT_WINDOW (userdata);
1960 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1961 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1963 if (gtk_check_menu_item_get_active (menu_item)) {
1965 WPTextBufferFormat format;
1967 memset (&format, 0, sizeof (format));
1968 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1970 label = gtk_bin_get_child (GTK_BIN (menu_item));
1972 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1973 format.cs.font_size = TRUE;
1974 format.cs.text_position = TRUE;
1975 format.cs.font = TRUE;
1976 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1977 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1979 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1980 (gpointer) wp_get_font_size_index (new_size_index, 12)))
1981 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1983 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1984 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1985 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1991 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1994 ModestMsgEditWindowPrivate *priv;
1995 gint new_font_index;
1996 ModestMsgEditWindow *window;
1999 window = MODEST_MSG_EDIT_WINDOW (userdata);
2000 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2001 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2003 if (gtk_check_menu_item_get_active (menu_item)) {
2006 label = gtk_bin_get_child (GTK_BIN (menu_item));
2008 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2010 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2011 (gpointer) new_font_index))
2012 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2014 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2015 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2016 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2022 modest_msg_edit_window_set_zoom (ModestWindow *window,
2025 ModestMsgEditWindowPrivate *priv;
2026 ModestWindowPrivate *parent_priv;
2027 GtkRadioAction *zoom_radio_action;
2029 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2031 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2032 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2033 priv->zoom_level = zoom;
2034 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom*DEFAULT_FONT_SCALE);
2036 /* Zoom level menu options should be updated with the current zoom level */
2037 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2038 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2039 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2040 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2041 /* FIXME: Not availible before Gtk 2.10 */
2043 gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
2048 modest_msg_edit_window_get_zoom (ModestWindow *window)
2050 ModestMsgEditWindowPrivate *priv;
2052 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
2054 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2055 return priv->zoom_level;
2059 zoom_allowed (ModestMsgEditWindow *window)
2063 focus = gtk_window_get_focus (GTK_WINDOW (window));
2064 return (focus != NULL && WP_IS_TEXT_VIEW (focus));
2068 modest_msg_edit_window_zoom_plus (ModestWindow *window)
2070 ModestWindowPrivate *parent_priv;
2071 GtkRadioAction *zoom_radio_action;
2072 GSList *group, *node;
2074 /* First we check if the text view is focused. If not, zooming is not allowed */
2075 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2076 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2080 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2081 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2082 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2084 group = gtk_radio_action_get_group (zoom_radio_action);
2086 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
2087 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
2091 for (node = group; node != NULL; node = g_slist_next (node)) {
2092 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
2093 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
2101 modest_msg_edit_window_zoom_minus (ModestWindow *window)
2103 ModestWindowPrivate *parent_priv;
2104 GtkRadioAction *zoom_radio_action;
2105 GSList *group, *node;
2107 /* First we check if the text view is focused. If not, zooming is not allowed */
2108 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2109 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2113 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2114 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2115 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2117 group = gtk_radio_action_get_group (zoom_radio_action);
2119 for (node = group; node != NULL; node = g_slist_next (node)) {
2120 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
2121 if (node->next != NULL) {
2122 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
2125 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
2133 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2135 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2136 ModestWindowPrivate *parent_priv;
2137 ModestWindowMgr *mgr;
2138 gboolean is_fullscreen;
2139 GtkAction *fs_toggle_action;
2142 mgr = modest_runtime_get_window_mgr ();
2143 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2145 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2147 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2148 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2149 if (is_fullscreen != active)
2150 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2158 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
2160 ModestWindowPrivate *parent_priv;
2161 GtkAction *fs_toggle_action;
2164 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2166 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2167 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
2168 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
2172 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2175 ModestMsgEditWindowPrivate *priv = NULL;
2176 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2178 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2179 if (!priv->update_caption_visibility)
2182 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2184 gtk_widget_show (priv->cc_caption);
2186 gtk_widget_hide (priv->cc_caption);
2188 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2192 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2195 ModestMsgEditWindowPrivate *priv = NULL;
2196 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2198 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2199 if (!priv->update_caption_visibility)
2202 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2204 gtk_widget_show (priv->bcc_caption);
2206 gtk_widget_hide (priv->bcc_caption);
2208 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2212 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2213 ModestRecptEditor *editor)
2215 ModestMsgEditWindowPrivate *priv;
2217 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2218 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2219 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2221 if (editor == NULL) {
2222 GtkWidget *view_focus;
2223 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2225 /* This code should be kept in sync with ModestRecptEditor. The
2226 textview inside the recpt editor is the one that really gets the
2227 focus. As it's inside a scrolled window, and this one inside the
2228 hbox recpt editor inherits from, we'll need to go up in the
2229 hierarchy to know if the text view is part of the recpt editor
2230 or if it's a different text entry */
2232 if (gtk_widget_get_parent (view_focus)) {
2233 GtkWidget *first_parent;
2235 first_parent = gtk_widget_get_parent (view_focus);
2236 if (gtk_widget_get_parent (first_parent) &&
2237 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2238 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2243 editor = MODEST_RECPT_EDITOR (priv->to_field);
2247 modest_address_book_select_addresses (editor);
2252 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2254 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2256 modest_msg_edit_window_open_addressbook (window, NULL);
2260 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2261 gboolean show_toolbar)
2263 ModestWindowPrivate *parent_priv;
2265 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2266 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2268 /* FIXME: we can not just use the code of
2269 modest_msg_edit_window_setup_toolbar because it has a
2270 mixture of both initialization and creation code. */
2273 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2275 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2279 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2280 TnyHeaderFlags priority_flags)
2282 ModestMsgEditWindowPrivate *priv;
2283 ModestWindowPrivate *parent_priv;
2285 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2287 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2288 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2289 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2291 if (priv->priority_flags != priority_flags) {
2292 GtkAction *priority_action = NULL;
2294 priv->priority_flags = priority_flags;
2296 switch (priority_flags) {
2297 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2298 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2299 gtk_widget_show (priv->priority_icon);
2300 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2301 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2303 case TNY_HEADER_FLAG_LOW_PRIORITY:
2304 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2305 gtk_widget_show (priv->priority_icon);
2306 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2307 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2310 gtk_widget_hide (priv->priority_icon);
2311 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2312 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2315 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2316 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2321 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2324 ModestMsgEditWindowPrivate *priv;
2325 ModestWindowPrivate *parent_priv;
2326 gint current_format;
2328 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2330 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2331 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2333 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2334 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2336 if (current_format != file_format) {
2337 switch (file_format) {
2338 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2339 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2341 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2345 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2346 response = gtk_dialog_run (GTK_DIALOG (dialog));
2347 gtk_widget_destroy (dialog);
2348 if (response == GTK_RESPONSE_OK) {
2349 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2351 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2352 modest_maemo_toggle_action_set_active_block_notify (action, TRUE);
2357 update_dimmed (window);
2362 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2365 ModestMsgEditWindowPrivate *priv;
2366 WPTextBufferFormat oldfmt, fmt;
2367 gint old_position = 0;
2371 GdkColor *color = NULL;
2372 gboolean bold, bold_set, italic, italic_set;
2373 gboolean underline, underline_set;
2374 gboolean strikethrough, strikethrough_set;
2375 gboolean position_set;
2376 gboolean font_size_set, font_set, color_set;
2379 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2380 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2382 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2384 /* First we get the currently selected font information */
2385 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2386 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2388 switch (oldfmt.text_position) {
2389 case TEXT_POSITION_NORMAL:
2392 case TEXT_POSITION_SUPERSCRIPT:
2400 g_object_set (G_OBJECT (dialog),
2401 "bold", oldfmt.bold != FALSE,
2402 "bold-set", !oldfmt.cs.bold,
2403 "underline", oldfmt.underline != FALSE,
2404 "underline-set", !oldfmt.cs.underline,
2405 "italic", oldfmt.italic != FALSE,
2406 "italic-set", !oldfmt.cs.italic,
2407 "strikethrough", oldfmt.strikethrough != FALSE,
2408 "strikethrough-set", !oldfmt.cs.strikethrough,
2409 "color", &oldfmt.color,
2410 "color-set", !oldfmt.cs.color,
2411 "size", wp_font_size[oldfmt.font_size],
2412 "size-set", !oldfmt.cs.font_size,
2413 "position", old_position,
2414 "position-set", !oldfmt.cs.text_position,
2415 "family", wp_get_font_name (oldfmt.font),
2416 "family-set", !oldfmt.cs.font,
2419 gtk_widget_show_all (dialog);
2420 response = gtk_dialog_run (GTK_DIALOG (dialog));
2421 if (response == GTK_RESPONSE_OK) {
2423 g_object_get( dialog,
2425 "bold-set", &bold_set,
2426 "underline", &underline,
2427 "underline-set", &underline_set,
2429 "italic-set", &italic_set,
2430 "strikethrough", &strikethrough,
2431 "strikethrough-set", &strikethrough_set,
2433 "color-set", &color_set,
2435 "size-set", &font_size_set,
2436 "family", &font_name,
2437 "family-set", &font_set,
2438 "position", &position,
2439 "position-set", &position_set,
2444 if (response == GTK_RESPONSE_OK) {
2445 memset(&fmt, 0, sizeof(fmt));
2451 fmt.italic = italic;
2452 fmt.cs.italic = TRUE;
2454 if (underline_set) {
2455 fmt.underline = underline;
2456 fmt.cs.underline = TRUE;
2458 if (strikethrough_set) {
2459 fmt.strikethrough = strikethrough;
2460 fmt.cs.strikethrough = TRUE;
2465 ? TEXT_POSITION_NORMAL
2466 : ( ( position == 1 )
2467 ? TEXT_POSITION_SUPERSCRIPT
2468 : TEXT_POSITION_SUBSCRIPT );
2469 fmt.cs.text_position = TRUE;
2473 fmt.cs.color = TRUE;
2476 fmt.font = wp_get_font_index(font_name,
2481 if (font_size_set) {
2482 fmt.font_size = wp_get_font_size_index(
2483 font_size, DEFAULT_FONT_SIZE);
2484 fmt.cs.font_size = TRUE;
2486 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2488 gtk_widget_destroy (dialog);
2490 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2494 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2496 ModestMsgEditWindowPrivate *priv;
2498 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2499 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2501 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2503 update_dimmed (window);
2508 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2510 ModestMsgEditWindowPrivate *priv;
2512 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2513 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2515 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2517 update_dimmed (window);
2522 update_dimmed (ModestMsgEditWindow *window)
2524 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2525 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2529 gboolean editor_focused;
2531 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2532 editor_focused = gtk_widget_is_focus (priv->msg_body);
2534 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2535 gtk_action_set_sensitive (action, rich_text && editor_focused);
2536 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2537 gtk_action_set_sensitive (action, rich_text && editor_focused);
2538 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2539 gtk_action_set_sensitive (action, rich_text && editor_focused);
2540 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2541 gtk_action_set_sensitive (action, rich_text && editor_focused);
2542 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2543 gtk_action_set_sensitive (action, rich_text && editor_focused);
2544 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2545 gtk_action_set_sensitive (action, rich_text && editor_focused);
2546 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2547 gtk_action_set_sensitive (action, rich_text && editor_focused);
2548 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2549 gtk_action_set_sensitive (action, rich_text && editor_focused);
2550 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2551 gtk_action_set_sensitive (action, rich_text && editor_focused);
2552 widget = priv->font_color_button;
2553 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2554 widget = priv->font_size_toolitem;
2555 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2556 widget = priv->font_face_toolitem;
2557 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2561 setup_insensitive_handlers (ModestMsgEditWindow *window)
2563 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2564 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2567 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2568 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2569 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2570 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2571 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2572 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2573 widget = priv->font_color_button;
2574 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2575 widget = priv->font_size_toolitem;
2576 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2577 widget = priv->font_face_toolitem;
2578 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2583 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2585 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2588 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2589 gtk_action_set_sensitive (action, can_undo);
2593 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2595 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2598 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/RedoMenu");
2599 gtk_action_set_sensitive (action, can_redo);
2603 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2606 GtkTextIter match_start, match_end;
2608 if (image_id == NULL)
2611 gtk_text_buffer_get_start_iter (buffer, &iter);
2613 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2614 GSList *tags = gtk_text_iter_get_tags (&match_start);
2616 for (node = tags; node != NULL; node = g_slist_next (node)) {
2617 GtkTextTag *tag = (GtkTextTag *) node->data;
2618 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2619 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2620 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2622 offset = gtk_text_iter_get_offset (&match_start);
2623 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2624 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2628 gtk_text_iter_forward_char (&iter);
2633 msg_body_focus (GtkWidget *focus,
2634 GdkEventFocus *event,
2638 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2643 recpt_field_changed (GtkTextBuffer *buffer,
2644 ModestMsgEditWindow *editor)
2646 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2647 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2648 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2649 gboolean dim = FALSE;
2652 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2653 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2654 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2656 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2657 gtk_text_buffer_get_char_count (cc_buffer) +
2658 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2660 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2661 gtk_action_set_sensitive (action, !dim);
2662 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2663 gtk_action_set_sensitive (action, !dim);
2667 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2669 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2673 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2675 gboolean rich_text, editor_focused;
2677 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2678 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2679 editor_focused = gtk_widget_is_focus (priv->msg_body);
2682 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2683 else if (!editor_focused)
2684 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2688 reset_modified (ModestMsgEditWindow *editor)
2690 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2691 GtkTextBuffer *buffer;
2693 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2694 gtk_text_buffer_set_modified (buffer, FALSE);
2695 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2696 gtk_text_buffer_set_modified (buffer, FALSE);
2697 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2698 gtk_text_buffer_set_modified (buffer, FALSE);
2699 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2703 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2705 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2706 GtkTextBuffer *buffer;
2708 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2709 if (gtk_text_buffer_get_modified (buffer))
2711 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2712 if (gtk_text_buffer_get_modified (buffer))
2714 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2715 if (gtk_text_buffer_get_modified (buffer))
2717 if (gtk_text_buffer_get_modified (priv->text_buffer))
2724 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
2726 ModestMsgEditWindowPrivate *priv = NULL;
2728 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2729 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2731 /* check if there's no recipient added */
2732 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2733 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2734 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2735 /* no recipient contents, then select contacts */
2736 modest_msg_edit_window_open_addressbook (window, NULL);
2740 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook))
2742 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook))
2744 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook))
2747 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2754 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2755 ModestMsgEditWindow *window)
2757 modest_msg_edit_window_offer_attach_file (window);
2761 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2763 ModestMsgEditWindow *window)
2765 ModestWindowPrivate *parent_priv;
2766 ModestMsgEditWindowPrivate *priv;
2768 gboolean has_selection;
2770 GList *selected_attachments = NULL;
2771 gint n_att_selected = 0;
2773 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2774 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2776 if (!GTK_WIDGET_VISIBLE (window))
2778 has_selection = gtk_clipboard_wait_for_targets (clipboard, NULL, NULL);
2779 focused = gtk_window_get_focus (GTK_WINDOW (window));
2781 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2782 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2783 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2784 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2786 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2787 n_att_selected = g_list_length (selected_attachments);
2788 g_list_free (selected_attachments);
2790 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2791 gtk_action_set_sensitive (action, n_att_selected == 1);
2793 update_paste_dimming (window);
2797 update_window_title (ModestMsgEditWindow *window)
2799 ModestMsgEditWindowPrivate *priv = NULL;
2800 const gchar *subject;
2802 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2803 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2804 if (subject == NULL || subject[0] == '\0')
2805 subject = _("mail_va_new_email");
2807 gtk_window_set_title (GTK_WINDOW (window), subject);
2812 subject_field_changed (GtkEditable *editable,
2813 ModestMsgEditWindow *window)
2815 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2816 update_window_title (window);
2817 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2821 subject_field_insert_text (GtkEditable *editable,
2823 gint new_text_length,
2825 ModestMsgEditWindow *window)
2827 GString *result = g_string_new ("");
2829 gint result_len = 0;
2831 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
2832 gunichar c = g_utf8_get_char_validated (current, 8);
2833 /* Invalid unichar, stop */
2839 result = g_string_append_unichar (result, c);
2843 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
2844 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
2846 g_signal_emit_by_name (editable, "insert-text",
2847 (gpointer) result->str, (gpointer) strlen (result->str),
2848 (gpointer) position, (gpointer) window);
2851 g_string_free (result, TRUE);
2855 message_is_empty (ModestMsgEditWindow *window)
2857 ModestMsgEditWindowPrivate *priv = NULL;
2859 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2860 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2862 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
2863 * so we can ignore markup.
2865 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
2868 count = gtk_text_buffer_get_char_count (buf);
2874 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2877 ModestMsgEditWindowPrivate *priv = NULL;
2879 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2880 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2882 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2885 gtk_widget_show_all (priv->find_toolbar);
2886 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2888 gtk_widget_hide_all (priv->find_toolbar);
2889 gtk_widget_grab_focus (priv->msg_body);
2895 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2897 GtkTextIter *match_start,
2898 GtkTextIter *match_end)
2900 GtkTextIter end_iter;
2901 gchar *str_casefold;
2904 gchar *range_casefold;
2907 gboolean result = FALSE;
2914 gtk_text_iter_forward_to_end (&end_iter);
2916 str_casefold = g_utf8_casefold (str, -1);
2917 str_chars_n = strlen (str);
2919 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2920 range_casefold = g_utf8_casefold (range_text, -1);
2921 range_chars_n = strlen (range_casefold);
2923 if (range_chars_n < str_chars_n) {
2924 g_free (str_casefold);
2925 g_free (range_text);
2926 g_free (range_casefold);
2930 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2931 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2932 if (!g_utf8_collate (range_subtext, str_casefold)) {
2933 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2935 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2936 match_start, match_end, NULL);
2937 g_free (found_text);
2939 g_free (range_subtext);
2943 g_free (str_casefold);
2944 g_free (range_text);
2945 g_free (range_casefold);
2952 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2953 ModestMsgEditWindow *window)
2955 gchar *current_search = NULL;
2956 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2958 GtkTextIter selection_start, selection_end;
2959 GtkTextIter match_start, match_end;
2960 gboolean continue_search = FALSE;
2962 if (message_is_empty (window)) {
2963 g_free (priv->last_search);
2964 priv->last_search = NULL;
2965 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
2969 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2970 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2971 g_free (current_search);
2972 g_free (priv->last_search);
2973 priv->last_search = NULL;
2974 /* Information banner about empty search */
2975 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2979 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2980 continue_search = TRUE;
2982 g_free (priv->last_search);
2983 priv->last_search = g_strdup (current_search);
2986 if (continue_search) {
2987 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2988 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2989 &match_start, &match_end);
2991 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2993 GtkTextIter buffer_start;
2994 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2995 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2996 &match_start, &match_end);
2998 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3001 /* Mark as selected the string found in search */
3003 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3004 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3006 g_free (priv->last_search);
3007 priv->last_search = NULL;
3009 g_free (current_search);
3013 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3014 ModestMsgEditWindow *window)
3016 GtkToggleAction *toggle;
3017 ModestWindowPrivate *parent_priv;
3018 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3020 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3021 gtk_toggle_action_set_active (toggle, FALSE);
3026 update_paste_dimming (ModestMsgEditWindow *window)
3028 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3029 GtkAction *action = NULL;
3030 GtkClipboard *clipboard = NULL;
3031 ModestEmailClipboard *e_clipboard;
3035 focused = gtk_window_get_focus (GTK_WINDOW (window));
3037 e_clipboard = modest_runtime_get_email_clipboard ();
3038 if (!modest_email_clipboard_cleared (e_clipboard)) {
3041 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3042 active = gtk_clipboard_wait_is_text_available (clipboard);
3046 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
3050 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
3051 gtk_action_set_sensitive (action, active);
3056 update_select_all_dimming (ModestMsgEditWindow *window)
3059 gboolean dimmed = FALSE;
3061 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3063 focused = gtk_window_get_focus (GTK_WINDOW (window));
3064 if (GTK_IS_ENTRY (focused)) {
3065 const gchar *current_text;
3066 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
3067 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
3068 } else if (GTK_IS_TEXT_VIEW (focused)) {
3069 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
3070 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
3071 } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
3074 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
3075 gtk_action_set_sensitive (action, !dimmed);
3079 update_zoom_dimming (ModestMsgEditWindow *window)
3082 gboolean dimmed = FALSE;
3084 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3086 focused = gtk_window_get_focus (GTK_WINDOW (window));
3087 dimmed = ! WP_IS_TEXT_VIEW (focused);
3088 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
3089 gtk_action_set_sensitive (action, !dimmed);
3093 edit_menu_activated (GtkAction *action,
3096 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3098 update_select_all_dimming (window);
3099 update_paste_dimming (window);
3102 view_menu_activated (GtkAction *action,
3105 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3107 update_zoom_dimming (window);
3111 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3113 ModestMsgEditWindowPrivate *priv;
3115 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3120 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3123 ModestMsgEditWindowPrivate *priv;
3125 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3131 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3134 ModestMsgEditWindowPrivate *priv;
3135 TnyHeader *header = NULL;
3137 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3138 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3140 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3141 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3143 if (priv->draft_msg != NULL) {
3144 header = tny_msg_get_header (priv->draft_msg);
3145 if (TNY_IS_HEADER (header)) {
3146 modest_window_mgr_unregister_header (mgr, header);
3148 g_object_unref (priv->draft_msg);
3151 if (draft != NULL) {
3152 g_object_ref (draft);
3153 header = tny_msg_get_header (draft);
3154 if (TNY_IS_HEADER (header))
3155 modest_window_mgr_register_header (mgr, header);
3156 if (priv->msg_uid) {
3157 g_free (priv->msg_uid);
3158 priv->msg_uid = NULL;
3160 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3163 priv->draft_msg = draft;
3167 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3168 GtkTextIter *start, GtkTextIter *end,
3171 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3172 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3175 if (tag == NULL+13) return;
3176 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3177 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3178 replace_with_attachments (window, priv->attachments);
3183 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3186 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3188 g_return_if_fail (TNY_IS_MIME_PART (part));
3189 priv->attachments = g_list_prepend (priv->attachments, part);
3190 g_object_ref (part);
3191 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part);
3192 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3193 gtk_widget_show_all (priv->attachments_caption);
3194 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3198 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3200 ModestMsgEditWindowPrivate *priv;
3202 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3203 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3205 return priv->msg_uid;