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"
65 #include "modest-msg-edit-window-ui-dimming.h"
67 #include "modest-hildon-includes.h"
68 #ifdef MODEST_HAVE_HILDON0_WIDGETS
69 #include <hildon-widgets/hildon-color-chooser.h>
71 #include "widgets/modest-msg-edit-window-ui.h"
72 #ifdef MODEST_HAVE_HILDON0_WIDGETS
73 #include <libgnomevfs/gnome-vfs-mime-utils.h>
75 #include <libgnomevfs/gnome-vfs-mime.h>
77 #include "modest-maemo-utils.h"
80 #define DEFAULT_FONT_SIZE 3
81 #define DEFAULT_FONT 2
82 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
83 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
84 #define DEFAULT_MAIN_VBOX_SPACING 6
85 #define SUBJECT_MAX_LENGTH 1000
86 #define IMAGE_MAX_WIDTH 560
87 #define DEFAULT_FONT_SCALE 1.5
89 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
90 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
91 static void modest_msg_edit_window_finalize (GObject *obj);
93 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
94 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
95 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
96 static void reset_modified (ModestMsgEditWindow *editor);
98 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
99 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
100 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
101 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
102 GtkTextIter *start, GtkTextIter *end,
104 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
105 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
106 static void subject_field_insert_text (GtkEditable *editable,
108 gint new_text_length,
110 ModestMsgEditWindow *window);
111 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
113 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
115 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
117 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
118 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
119 GdkEventWindowState *event,
121 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
122 ModestRecptEditor *editor);
123 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
124 ModestMsgEditWindow *window);
126 /* ModestWindow methods implementation */
127 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
128 static void modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom);
129 static gdouble modest_msg_edit_window_get_zoom (ModestWindow *window);
130 static gboolean modest_msg_edit_window_zoom_minus (ModestWindow *window);
131 static gboolean modest_msg_edit_window_zoom_plus (ModestWindow *window);
132 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
133 gboolean show_toolbar);
134 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
136 ModestMsgEditWindow *window);
137 static void subject_field_move_cursor (GtkEntry *entry,
138 GtkMovementStep step,
142 static void update_window_title (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 /* list my signals */
206 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
207 struct _ModestMsgEditWindowPrivate {
209 GtkWidget *header_box;
211 ModestPairList *from_field_protos;
212 GtkWidget *from_field;
216 GtkWidget *bcc_field;
217 GtkWidget *subject_field;
218 GtkWidget *attachments_view;
219 GtkWidget *priority_icon;
220 GtkWidget *add_attachment_button;
222 GtkWidget *cc_caption;
223 GtkWidget *bcc_caption;
224 gboolean update_caption_visibility;
225 GtkWidget *attachments_caption;
227 GtkTextBuffer *text_buffer;
229 GtkWidget *font_size_toolitem;
230 GtkWidget *font_face_toolitem;
231 GtkWidget *font_color_button;
232 GSList *font_items_group;
233 GtkWidget *font_tool_button_label;
234 GSList *size_items_group;
235 GtkWidget *size_tool_button_label;
237 GtkWidget *find_toolbar;
241 GtkWidget *scroll_area;
242 gint last_vadj_upper;
247 TnyHeaderFlags priority_flags;
251 gboolean can_undo, can_redo;
252 gulong clipboard_change_handler_id;
253 gulong default_clipboard_change_handler_id;
254 gchar *clipboard_text;
263 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
264 MODEST_TYPE_MSG_EDIT_WINDOW, \
265 ModestMsgEditWindowPrivate))
267 static GtkWindowClass *parent_class = NULL;
269 /* uncomment the following if you have defined any signals */
270 /* static guint signals[LAST_SIGNAL] = {0}; */
273 modest_msg_edit_window_get_type (void)
275 static GType my_type = 0;
277 static const GTypeInfo my_info = {
278 sizeof(ModestMsgEditWindowClass),
279 NULL, /* base init */
280 NULL, /* base finalize */
281 (GClassInitFunc) modest_msg_edit_window_class_init,
282 NULL, /* class finalize */
283 NULL, /* class data */
284 sizeof(ModestMsgEditWindow),
286 (GInstanceInitFunc) modest_msg_edit_window_init,
289 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
290 "ModestMsgEditWindow",
293 wp_text_buffer_library_init ();
299 save_state (ModestWindow *self)
301 modest_widget_memory_save (modest_runtime_get_conf(),
302 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
307 restore_settings (ModestMsgEditWindow *self)
309 modest_widget_memory_restore (modest_runtime_get_conf(),
310 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
315 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
317 GObjectClass *gobject_class;
318 ModestWindowClass *modest_window_class;
319 gobject_class = (GObjectClass*) klass;
320 modest_window_class = (ModestWindowClass*) klass;
322 parent_class = g_type_class_peek_parent (klass);
323 gobject_class->finalize = modest_msg_edit_window_finalize;
325 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
326 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
327 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
328 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
329 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
330 modest_window_class->save_state_func = save_state;
331 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
333 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
337 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
339 ModestMsgEditWindowPrivate *priv;
340 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
342 priv->msg_body = NULL;
343 priv->from_field = NULL;
344 priv->to_field = NULL;
345 priv->cc_field = NULL;
346 priv->bcc_field = NULL;
347 priv->subject_field = NULL;
348 priv->attachments = NULL;
350 priv->zoom_level = 1.0;
352 priv->cc_caption = NULL;
353 priv->bcc_caption = NULL;
354 priv->update_caption_visibility = FALSE;
356 priv->priority_flags = 0;
358 priv->find_toolbar = NULL;
359 priv->last_search = NULL;
361 priv->draft_msg = NULL;
362 priv->outbox_msg = NULL;
363 priv->msg_uid = NULL;
365 priv->can_undo = FALSE;
366 priv->can_redo = FALSE;
367 priv->clipboard_change_handler_id = 0;
368 priv->default_clipboard_change_handler_id = 0;
369 priv->clipboard_text = NULL;
372 priv->last_vadj_upper = 0;
376 /* FIXME: this is a dup from the one in gtk/ */
379 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
381 static ModestPairList*
382 get_transports (void)
384 GSList *transports = NULL;
386 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
387 GSList *accounts = modest_account_mgr_account_names (account_mgr,
388 TRUE /* only enabled accounts. */);
390 GSList *cursor = accounts;
392 gchar *account_name = cursor->data;
393 gchar *from_string = NULL;
395 from_string = modest_account_mgr_get_from_string (account_mgr,
399 if (from_string && account_name) {
400 gchar *name = account_name;
401 ModestPair *pair = modest_pair_new ((gpointer) name,
402 (gpointer) from_string , TRUE);
403 transports = g_slist_prepend (transports, pair);
406 cursor = cursor->next;
408 g_slist_free (accounts); /* only free the accounts, not the elements,
409 * because they are used in the pairlist */
413 void vadj_changed (GtkAdjustment *adj,
414 ModestMsgEditWindow *window)
416 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
418 GdkRectangle rectangle, cursor_rectangle;
419 GtkTextIter position;
423 /* We detect if cursor is visible using the full height, not only the center. This
425 gtk_text_view_get_visible_rect (GTK_TEXT_VIEW (priv->msg_body), &rectangle);
426 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer),
428 gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer)));
429 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &position, &cursor_rectangle);
431 cursor_bottom = (cursor_rectangle.y + cursor_rectangle.height);
432 visible = (cursor_rectangle.y >= rectangle.y) && (cursor_bottom < (rectangle.y + rectangle.height));
434 if (gtk_widget_is_focus (priv->msg_body) &&
436 if (priv->last_vadj_upper != adj->upper) {
439 insert = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
440 gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (priv->msg_body),
441 insert, 0.1, FALSE, 0.0, 0.0);
444 priv->last_vadj_upper = adj->upper;
449 init_window (ModestMsgEditWindow *obj)
451 GtkWidget *from_caption, *to_caption, *subject_caption;
452 GtkWidget *main_vbox;
453 ModestMsgEditWindowPrivate *priv;
455 GtkSizeGroup *size_group;
457 GtkWidget *subject_box;
458 GtkWidget *attachment_icon;
459 GtkWidget *window_box;
460 #if (GTK_MINOR_VERSION >= 10)
461 GdkAtom deserialize_type;
463 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
465 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
467 /* Note: This ModestPairList* must exist for as long as the combo
468 * that uses it, because the ModestComboBox uses the ID opaquely,
469 * so it can't know how to manage its memory. */
470 priv->from_field_protos = get_transports ();
472 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
474 priv->to_field = modest_recpt_editor_new ();
475 priv->cc_field = modest_recpt_editor_new ();
476 priv->bcc_field = modest_recpt_editor_new ();
477 subject_box = gtk_hbox_new (FALSE, 0);
478 priv->priority_icon = gtk_image_new ();
479 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
480 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
481 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
482 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
483 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
484 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
485 priv->add_attachment_button = gtk_button_new ();
486 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
487 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
488 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
489 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
490 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
491 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
492 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
493 priv->attachments_view = modest_attachments_view_new (NULL);
495 priv->header_box = gtk_vbox_new (FALSE, 0);
497 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
498 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
499 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
500 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
501 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
502 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
503 g_object_unref (size_group);
505 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
506 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
507 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
508 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
509 gtk_size_group_add_widget (size_group, priv->subject_field);
510 gtk_size_group_add_widget (size_group, priv->attachments_view);
511 g_object_unref (size_group);
513 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
514 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
515 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
516 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
517 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
518 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
519 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
522 priv->msg_body = wp_text_view_new ();
523 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
524 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
525 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
526 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
527 #if (GTK_MINOR_VERSION >= 10)
528 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
529 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
531 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
532 deserialize_type, TRUE);
534 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
536 priv->find_toolbar = hildon_find_toolbar_new (NULL);
537 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
539 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
541 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
542 G_CALLBACK (text_buffer_refresh_attributes), obj);
543 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
544 G_CALLBACK (text_buffer_can_undo), obj);
545 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
546 G_CALLBACK (text_buffer_can_redo), obj);
547 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
548 G_CALLBACK (body_changed), obj);
549 g_signal_connect (G_OBJECT (obj), "window-state-event",
550 G_CALLBACK (modest_msg_edit_window_window_state_event),
552 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
553 G_CALLBACK (text_buffer_apply_tag), obj);
554 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
555 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
556 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
557 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
558 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
559 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
561 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
562 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
564 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
565 G_CALLBACK (msg_body_focus), obj);
566 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
567 G_CALLBACK (msg_body_focus), obj);
568 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
569 "changed", G_CALLBACK (recpt_field_changed), obj);
570 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
571 "changed", G_CALLBACK (recpt_field_changed), obj);
572 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
573 "changed", G_CALLBACK (recpt_field_changed), obj);
574 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
575 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
576 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
578 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
579 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
581 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
582 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
583 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
584 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
586 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
588 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
589 frame = gtk_frame_new (NULL);
590 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
592 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
593 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
594 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
596 G_CALLBACK (vadj_changed),
598 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
600 window_box = gtk_vbox_new (FALSE, 0);
601 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
602 gtk_container_add (GTK_CONTAINER(obj), window_box);
603 priv->scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
604 gtk_container_add (GTK_CONTAINER (frame), priv->scroll_area);
606 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
607 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
608 priv->default_clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
609 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
614 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
616 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
618 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
619 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
620 priv->clipboard_change_handler_id))
621 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
622 priv->clipboard_change_handler_id);
623 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
624 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
625 priv->default_clipboard_change_handler_id))
626 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
627 priv->default_clipboard_change_handler_id);
631 modest_msg_edit_window_finalize (GObject *obj)
633 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
635 /* Sanity check: shouldn't be needed, the window mgr should
636 call this function before */
637 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
639 if (priv->clipboard_text != NULL) {
640 g_free (priv->clipboard_text);
641 priv->clipboard_text = NULL;
644 if (priv->draft_msg != NULL) {
645 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
646 if (TNY_IS_HEADER (header)) {
647 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
648 modest_window_mgr_unregister_header (mgr, header);
650 g_object_unref (priv->draft_msg);
651 priv->draft_msg = NULL;
653 if (priv->outbox_msg != NULL) {
654 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
655 if (TNY_IS_HEADER (header)) {
656 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
657 modest_window_mgr_unregister_header (mgr, header);
659 g_object_unref (priv->outbox_msg);
660 priv->outbox_msg = NULL;
662 if (priv->msg_uid != NULL) {
663 g_free (priv->msg_uid);
664 priv->msg_uid = NULL;
667 /* This had to stay alive for as long as the combobox that used it: */
668 modest_pair_list_free (priv->from_field_protos);
670 G_OBJECT_CLASS(parent_class)->finalize (obj);
674 menubar_to_menu (GtkUIManager *ui_manager)
676 GtkWidget *main_menu;
680 /* Create new main menu */
681 main_menu = gtk_menu_new();
683 /* Get the menubar from the UI manager */
684 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
686 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
690 menu = GTK_WIDGET (iter->data);
691 gtk_widget_reparent(menu, main_menu);
693 iter = g_list_next (iter);
699 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type)
701 GdkPixbufLoader *loader;
704 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
709 tny_stream_reset (TNY_STREAM (stream));
710 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
711 unsigned char read_buffer[128];
713 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
714 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
718 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
719 g_object_ref (pixbuf);
720 gdk_pixbuf_loader_close (loader, NULL);
721 g_object_unref (loader);
723 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
724 GdkPixbuf *new_pixbuf;
726 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
727 gdk_pixbuf_get_width (pixbuf);
728 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
729 g_object_unref (pixbuf);
737 replace_with_attachments (ModestMsgEditWindow *self, GList *attachments)
739 ModestMsgEditWindowPrivate *priv;
742 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
744 for (node = attachments; node != NULL; node = g_list_next (node)) {
745 TnyMimePart *part = (TnyMimePart *) node->data;
746 const gchar *cid = tny_mime_part_get_content_id (part);
747 const gchar *mime_type = tny_mime_part_get_content_type (part);
748 if ((cid != NULL)&&(mime_type != NULL)) {
749 TnyStream *stream = tny_mime_part_get_stream (part);
750 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type);
751 g_object_unref (stream);
753 if (pixbuf != NULL) {
754 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
755 g_object_unref (pixbuf);
762 update_last_cid (ModestMsgEditWindow *self, GList *attachments)
765 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
767 for (node = attachments; node != NULL; node = g_list_next (node)) {
768 TnyMimePart *part = (TnyMimePart *) node->data;
769 const gchar *cid = tny_mime_part_get_content_id (part);
771 char *invalid = NULL;
772 gint int_cid = strtol (cid, &invalid, 10);
773 if ((invalid != NULL) && (*invalid == '\0') && (int_cid > priv->last_cid)) {
774 priv->last_cid = int_cid;
782 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
785 const gchar *to, *cc, *bcc, *subject;
787 ModestMsgEditWindowPrivate *priv;
789 TnyHeaderFlags priority_flags;
790 TnyFolder *msg_folder;
791 gboolean is_html = FALSE;
793 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
794 g_return_if_fail (TNY_IS_MSG (msg));
796 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
798 header = tny_msg_get_header (msg);
799 to = tny_header_get_to (header);
800 cc = tny_header_get_cc (header);
801 bcc = tny_header_get_bcc (header);
802 subject = tny_header_get_subject (header);
803 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
806 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
808 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
809 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
810 gtk_widget_show (priv->cc_caption);
811 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
812 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
813 gtk_widget_hide (priv->cc_caption);
816 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
817 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
818 gtk_widget_show (priv->bcc_caption);
819 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
820 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
821 gtk_widget_hide (priv->bcc_caption);
824 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
825 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
828 update_window_title (self);
830 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
831 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
833 if ((body == NULL)||(body[0] == '\0')) {
835 body = modest_text_utils_convert_to_html ("");
838 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
839 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
842 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
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 if (preserve_is_rich && !is_html) {
858 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
859 /* Get the default format required from configuration */
860 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
861 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
864 /* Set the default focus depending on having already a To: field or not */
865 if ((!to)||(*to == '\0')) {
866 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
868 gtk_widget_grab_focus (priv->msg_body);
871 /* TODO: lower priority, select in the From: combo to the
872 value that comes from msg <- not sure, should it be
875 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
877 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
878 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
880 reset_modified (self);
882 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
883 text_buffer_can_undo (priv->text_buffer, FALSE, self);
884 text_buffer_can_redo (priv->text_buffer, FALSE, self);
887 g_free (priv->msg_uid);
888 priv->msg_uid = NULL;
891 /* we should set a reference to the incoming message if it is a draft */
892 msg_folder = tny_msg_get_folder (msg);
894 if (modest_tny_folder_is_local_folder (msg_folder)) {
895 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
896 if (type == TNY_FOLDER_TYPE_DRAFTS)
897 priv->draft_msg = g_object_ref(msg);
898 if (type == TNY_FOLDER_TYPE_OUTBOX)
899 priv->outbox_msg = g_object_ref(msg);
900 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
902 g_object_unref (msg_folder);
907 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
910 GList *item_children, *node;
911 GtkWidget *bin_child;
913 bin_child = gtk_bin_get_child (GTK_BIN(item));
915 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
917 for (node = item_children; node != NULL; node = g_list_next (node)) {
918 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
919 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
922 g_list_free (item_children);
926 menu_tool_button_dont_expand (GtkMenuToolButton *item)
929 GList *item_children, *node;
931 box = gtk_bin_get_child (GTK_BIN (item));
932 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
933 item_children = gtk_container_get_children (GTK_CONTAINER (box));
935 for (node = item_children; node != NULL; node = g_list_next (node)) {
936 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
937 if (GTK_IS_TOGGLE_BUTTON (node->data))
938 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
939 else if (GTK_IS_BUTTON (node->data))
940 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
942 g_list_free (item_children);
947 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
949 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
950 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
951 GtkWidget *placeholder;
952 GtkWidget *tool_item;
957 GtkWidget *sizes_menu;
958 GtkWidget *fonts_menu;
959 GSList *radio_group = NULL;
964 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
965 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
967 /* Font color placeholder */
968 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
969 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
972 tool_item = GTK_WIDGET (gtk_tool_item_new ());
973 priv->font_color_button = hildon_color_button_new ();
974 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
975 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
976 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
977 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
978 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
979 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
980 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
982 G_CALLBACK (modest_msg_edit_window_color_button_change),
985 /* Font size and face placeholder */
986 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
987 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
989 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
990 priv->size_tool_button_label = gtk_label_new (NULL);
991 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
992 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
993 size_text,"</span>", NULL);
994 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
996 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
997 sizes_menu = gtk_menu_new ();
998 priv->size_items_group = NULL;
1000 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1001 GtkWidget *size_menu_item;
1003 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1004 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1005 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1006 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1007 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1008 gtk_widget_show (size_menu_item);
1010 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1014 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1015 GtkWidget *item = (GtkWidget *) node->data;
1016 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1020 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1021 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1022 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1023 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1024 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1025 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1026 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1027 priv->font_size_toolitem = tool_item;
1030 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1031 priv->font_tool_button_label = gtk_label_new (NULL);
1032 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1033 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1035 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1036 fonts_menu = gtk_menu_new ();
1037 priv->font_items_group = NULL;
1039 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1040 GtkWidget *font_menu_item;
1041 GtkWidget *child_label;
1043 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1044 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1045 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1046 wp_get_font_name (font_index), "</span>", NULL);
1047 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1050 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1051 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1052 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1053 gtk_widget_show (font_menu_item);
1055 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1058 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1059 GtkWidget *item = (GtkWidget *) node->data;
1060 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1063 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1064 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1065 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1066 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1067 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1068 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1069 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1070 priv->font_face_toolitem = tool_item;
1072 /* Set expand and homogeneous for remaining items */
1073 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1074 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1075 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1076 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1077 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1078 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1079 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1080 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1081 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1083 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1084 will not show the tool items added to the placeholders) */
1085 gtk_widget_show_all (parent_priv->toolbar);
1087 /* Set the no show all *after* showing all items. We do not
1088 want the toolbar to be shown with a show all because it
1089 could go agains the gconf setting regarding showing or not
1090 the toolbar of the editor window */
1091 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1097 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1100 ModestWindowPrivate *parent_priv;
1101 ModestMsgEditWindowPrivate *priv;
1102 GtkActionGroup *action_group;
1103 GError *error = NULL;
1104 GdkPixbuf *window_icon = NULL;
1107 ModestPair *account_pair = NULL;
1108 ModestDimmingRulesGroup *menu_rules_group = NULL;
1109 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1110 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1112 g_return_val_if_fail (msg, NULL);
1113 g_return_val_if_fail (account_name, NULL);
1115 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
1117 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1118 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1120 parent_priv->ui_manager = gtk_ui_manager_new();
1121 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
1122 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1124 /* Add common actions */
1125 gtk_action_group_add_actions (action_group,
1126 modest_msg_edit_action_entries,
1127 G_N_ELEMENTS (modest_msg_edit_action_entries),
1129 gtk_action_group_add_toggle_actions (action_group,
1130 modest_msg_edit_toggle_action_entries,
1131 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
1133 gtk_action_group_add_radio_actions (action_group,
1134 modest_msg_edit_alignment_radio_action_entries,
1135 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
1137 G_CALLBACK (modest_ui_actions_on_change_justify),
1139 gtk_action_group_add_radio_actions (action_group,
1140 modest_msg_edit_zoom_action_entries,
1141 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
1143 G_CALLBACK (modest_ui_actions_on_change_zoom),
1145 gtk_action_group_add_radio_actions (action_group,
1146 modest_msg_edit_priority_action_entries,
1147 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
1149 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
1151 gtk_action_group_add_radio_actions (action_group,
1152 modest_msg_edit_file_format_action_entries,
1153 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
1154 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
1155 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
1157 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1158 g_object_unref (action_group);
1160 /* Load the UI definition */
1161 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
1163 if (error != NULL) {
1164 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
1165 g_clear_error (&error);
1168 /* Add accelerators */
1169 gtk_window_add_accel_group (GTK_WINDOW (obj),
1170 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1172 /* Menubar. Update the state of some toggles */
1173 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
1174 conf = modest_runtime_get_conf ();
1175 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1176 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
1177 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1178 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL));
1179 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1180 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu");
1181 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1182 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1184 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1187 init_window (MODEST_MSG_EDIT_WINDOW(obj));
1189 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1191 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1193 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1194 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1196 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
1197 if (account_pair != NULL)
1198 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
1200 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1201 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
1202 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
1203 clipboard_rules_group = modest_dimming_rules_group_new ("ModestClipboardDimmingRules", FALSE);
1204 /* Add common dimming rules */
1205 modest_dimming_rules_group_add_rules (menu_rules_group,
1206 modest_msg_edit_window_menu_dimming_entries,
1207 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1208 MODEST_WINDOW (obj));
1209 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1210 modest_msg_edit_window_toolbar_dimming_entries,
1211 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1212 MODEST_WINDOW (obj));
1213 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1214 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1215 MODEST_WINDOW (obj));
1216 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1217 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1218 MODEST_WINDOW (obj));
1219 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1220 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1221 MODEST_WINDOW (obj));
1222 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1223 modest_msg_edit_window_clipboard_dimming_entries,
1224 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1225 MODEST_WINDOW (obj));
1226 /* Insert dimming rules group for this window */
1227 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1228 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1229 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1230 /* Checks the dimming rules */
1231 g_object_unref (menu_rules_group);
1232 g_object_unref (toolbar_rules_group);
1233 g_object_unref (clipboard_rules_group);
1235 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1237 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1239 /* Set window icon */
1240 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
1242 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1243 g_object_unref (window_icon);
1246 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1247 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), "ModestClipboardDimmingRules");
1249 /* Dim at start clipboard actions */
1250 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
1251 gtk_action_set_sensitive (action, FALSE);
1252 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
1253 gtk_action_set_sensitive (action, FALSE);
1254 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
1255 gtk_action_set_sensitive (action, FALSE);
1257 /* set initial state of cc and bcc */
1258 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
1259 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1260 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
1261 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
1262 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1263 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
1265 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), "ModestClipboardDimmingRules");
1266 priv->update_caption_visibility = TRUE;
1268 reset_modified (MODEST_MSG_EDIT_WINDOW (obj));
1270 return (ModestWindow*) obj;
1274 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1276 GString **string_buffer = (GString **) user_data;
1278 *string_buffer = g_string_append (*string_buffer, buffer);
1284 * @result: A new string which should be freed with g_free().
1287 get_formatted_data (ModestMsgEditWindow *edit_window)
1289 ModestMsgEditWindowPrivate *priv;
1290 GString *string_buffer = g_string_new ("");
1292 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1294 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1296 return g_string_free (string_buffer, FALSE);
1301 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1304 const gchar *account_name;
1305 ModestMsgEditWindowPrivate *priv;
1307 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1309 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1311 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1312 g_return_val_if_fail (account_name, NULL);
1315 /* don't free these (except from) */
1316 data = g_slice_new0 (MsgData);
1317 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1319 data->account_name = g_strdup (account_name);
1320 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1321 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1322 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1323 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1324 if (priv->draft_msg) {
1325 data->draft_msg = g_object_ref (priv->draft_msg);
1326 } else if (priv->outbox_msg) {
1327 data->draft_msg = g_object_ref (priv->outbox_msg);
1329 data->draft_msg = NULL;
1332 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1334 gtk_text_buffer_get_bounds (buf, &b, &e);
1335 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1337 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1338 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1340 data->html_body = NULL;
1342 /* deep-copy the data */
1343 GList *cursor = priv->attachments;
1344 data->attachments = NULL;
1346 if (!(TNY_IS_MIME_PART(cursor->data))) {
1347 g_warning ("strange data in attachment list");
1348 cursor = g_list_next (cursor);
1351 data->attachments = g_list_append (data->attachments,
1352 g_object_ref (cursor->data));
1353 cursor = g_list_next (cursor);
1356 data->priority_flags = priv->priority_flags;
1363 unref_gobject (GObject *obj, gpointer data)
1365 if (!G_IS_OBJECT(obj))
1367 g_object_unref (obj);
1371 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1374 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1382 g_free (data->subject);
1383 g_free (data->plain_body);
1384 g_free (data->html_body);
1385 g_free (data->account_name);
1387 if (data->draft_msg != NULL) {
1388 g_object_unref (data->draft_msg);
1389 data->draft_msg = NULL;
1392 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1393 g_list_free (data->attachments);
1395 g_slice_free (MsgData, data);
1399 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1402 ModestMsgEditWindowPrivate *priv = NULL;
1403 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1405 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1407 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1409 return MODEST_MSG_EDIT_FORMAT_HTML;
1411 return MODEST_MSG_EDIT_FORMAT_TEXT;
1415 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1416 ModestMsgEditFormat format)
1418 ModestMsgEditWindowPrivate *priv;
1420 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1421 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1424 case MODEST_MSG_EDIT_FORMAT_HTML:
1425 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1427 case MODEST_MSG_EDIT_FORMAT_TEXT:
1428 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1431 g_return_if_reached ();
1435 ModestMsgEditFormatState *
1436 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1438 ModestMsgEditFormatState *format_state = NULL;
1439 ModestMsgEditWindowPrivate *priv;
1440 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1442 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1443 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1445 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1447 format_state = g_new0 (ModestMsgEditFormatState, 1);
1448 format_state->bold = buffer_format->bold&0x1;
1449 format_state->italics = buffer_format->italic&0x1;
1450 format_state->bullet = buffer_format->bullet&0x1;
1451 format_state->color = buffer_format->color;
1452 format_state->font_size = buffer_format->font_size;
1453 format_state->font_family = wp_get_font_name (buffer_format->font);
1454 format_state->justification = buffer_format->justification;
1455 g_free (buffer_format);
1457 return format_state;
1462 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1463 const ModestMsgEditFormatState *format_state)
1465 ModestMsgEditWindowPrivate *priv;
1466 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1467 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1468 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1469 g_return_if_fail (format_state != NULL);
1471 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1472 gtk_widget_grab_focus (priv->msg_body);
1473 buffer_format->bold = (format_state->bold != FALSE);
1474 buffer_format->italic = (format_state->italics != FALSE);
1475 buffer_format->color = format_state->color;
1476 buffer_format->font_size = format_state->font_size;
1477 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1478 buffer_format->justification = format_state->justification;
1479 buffer_format->bullet = format_state->bullet;
1481 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1483 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1484 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1485 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1486 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1487 buffer_format->cs.font = (buffer_format->font != current_format->font);
1488 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1489 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1491 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1492 if (buffer_format->cs.bold) {
1493 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1495 if (buffer_format->cs.italic) {
1496 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1498 if (buffer_format->cs.color) {
1499 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1501 if (buffer_format->cs.font_size) {
1502 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1504 if (buffer_format->cs.justification) {
1505 switch (buffer_format->justification) {
1506 case GTK_JUSTIFY_LEFT:
1507 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1509 case GTK_JUSTIFY_CENTER:
1510 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1512 case GTK_JUSTIFY_RIGHT:
1513 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1520 if (buffer_format->cs.font) {
1521 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1523 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1524 if (buffer_format->cs.bullet) {
1525 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((buffer_format->bullet)?1:0));
1527 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1529 g_free (current_format);
1534 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1536 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1538 ModestWindowPrivate *parent_priv;
1539 ModestMsgEditWindowPrivate *priv;
1540 GtkWidget *new_size_menuitem;
1541 GtkWidget *new_font_menuitem;
1543 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1544 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1546 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1547 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1548 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1549 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1551 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1552 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1553 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1556 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1558 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1559 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1561 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1562 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1564 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1565 /* modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1567 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1568 G_CALLBACK (modest_msg_edit_window_color_button_change),
1570 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1571 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1572 G_CALLBACK (modest_msg_edit_window_color_button_change),
1575 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1576 buffer_format->font_size))->data);
1577 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1581 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1582 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1583 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1585 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1586 G_CALLBACK (modest_msg_edit_window_size_change),
1588 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1589 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1590 G_CALLBACK (modest_msg_edit_window_size_change),
1594 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1595 buffer_format->font))->data);
1596 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1600 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1601 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1602 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1604 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1605 G_CALLBACK (modest_msg_edit_window_font_change),
1607 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1608 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1609 G_CALLBACK (modest_msg_edit_window_font_change),
1613 g_free (buffer_format);
1619 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1622 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1623 ModestMsgEditWindowPrivate *priv;
1624 GtkWidget *dialog = NULL;
1626 const GdkColor *new_color = NULL;
1628 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1629 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1631 #ifdef MODEST_HILDON_VERSION_0
1632 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1633 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1635 dialog = hildon_color_chooser_new ();
1636 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1637 #endif /*MODEST_HILDON_VERSION_0*/
1638 g_free (buffer_format);
1640 response = gtk_dialog_run (GTK_DIALOG (dialog));
1642 case GTK_RESPONSE_OK: {
1643 #ifdef MODEST_HILDON_VERSION_0
1644 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1647 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1649 #endif /*MODEST_HILDON_VERSION_0*/
1656 gtk_widget_destroy (dialog);
1658 if (new_color != NULL)
1659 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1664 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1667 ModestMsgEditWindowPrivate *priv;
1668 GtkWidget *dialog = NULL;
1670 GdkColor *old_color = NULL;
1671 const GdkColor *new_color = NULL;
1673 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1674 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1676 #ifdef MODEST_HILDON_VERSION_0
1677 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1678 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1680 dialog = hildon_color_chooser_new ();
1681 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1682 #endif /*MODEST_HILDON_VERSION_9*/
1684 response = gtk_dialog_run (GTK_DIALOG (dialog));
1686 case GTK_RESPONSE_OK: {
1687 #ifdef MODEST_HILDON_VERSION_0
1688 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1691 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1693 #endif /*MODEST_HILDON_VERSION_0*/
1699 gtk_widget_destroy (dialog);
1701 if (new_color != NULL)
1702 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1706 static TnyStream* create_stream_for_uri (const gchar* uri)
1711 TnyStream *result = NULL;
1713 GnomeVFSHandle *handle = NULL;
1714 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1715 if (test == GNOME_VFS_OK) {
1716 /* Create the tinymail stream: */
1717 /* Presumably tinymai will call gnome_vfs_close (handle) later. */
1718 result = TNY_STREAM (tny_vfs_stream_new (handle));
1725 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1728 ModestMsgEditWindowPrivate *priv;
1729 GtkWidget *dialog = NULL;
1731 GSList *uris = NULL;
1732 GSList *uri_node = NULL;
1734 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1736 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1737 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1738 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1740 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1742 response = gtk_dialog_run (GTK_DIALOG (dialog));
1744 case GTK_RESPONSE_OK:
1745 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1750 gtk_widget_destroy (dialog);
1752 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1754 GnomeVFSHandle *handle = NULL;
1755 GnomeVFSResult result;
1756 GtkTextIter position;
1757 GtkTextMark *insert_mark;
1759 uri = (const gchar *) uri_node->data;
1760 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1761 if (result == GNOME_VFS_OK) {
1763 GnomeVFSFileInfo info;
1764 gchar *filename, *basename, *escaped_filename;
1765 TnyMimePart *mime_part;
1767 const gchar *mime_type = NULL;
1768 GnomeVFSURI *vfs_uri;
1770 vfs_uri = gnome_vfs_uri_new (uri);
1772 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1773 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1774 g_free (escaped_filename);
1775 gnome_vfs_uri_unref (vfs_uri);
1777 if (gnome_vfs_get_file_info (uri, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
1778 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1780 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1782 mime_part = tny_platform_factory_new_mime_part
1783 (modest_runtime_get_platform_factory ());
1785 TnyStream *stream = create_stream_for_uri (uri);
1786 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1788 content_id = g_strdup_printf ("%d", priv->last_cid);
1789 tny_mime_part_set_content_id (mime_part, content_id);
1790 g_free (content_id);
1793 basename = g_path_get_basename (filename);
1794 tny_mime_part_set_filename (mime_part, basename);
1797 pixbuf = pixbuf_from_stream (stream, mime_type);
1799 if (pixbuf != NULL) {
1800 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1801 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1802 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1805 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1806 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1808 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1809 gtk_widget_show_all (priv->attachments_caption);
1810 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1820 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
1823 ModestMsgEditWindowPrivate *priv;
1824 GtkWidget *dialog = NULL;
1826 GSList *uris = NULL;
1829 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1831 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1832 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
1833 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1835 response = gtk_dialog_run (GTK_DIALOG (dialog));
1837 case GTK_RESPONSE_OK:
1838 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1843 gtk_widget_destroy (dialog);
1845 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1846 const gchar *uri = (const gchar *) uri_node->data;
1847 modest_msg_edit_window_attach_file_one (window, uri);
1849 g_slist_foreach (uris, (GFunc) g_free, NULL);
1850 g_slist_free (uris);
1854 modest_msg_edit_window_attach_file_one (
1855 ModestMsgEditWindow *window,
1858 g_return_if_fail (window);
1859 g_return_if_fail (uri);
1861 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1864 GnomeVFSHandle *handle = NULL;
1865 GnomeVFSResult result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1866 if (result == GNOME_VFS_OK) {
1867 TnyMimePart *mime_part;
1869 const gchar *mime_type = NULL;
1871 gchar *escaped_filename;
1874 GnomeVFSFileInfo info;
1875 GnomeVFSURI *vfs_uri;
1877 vfs_uri = gnome_vfs_uri_new (uri);
1880 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1881 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1882 g_free (escaped_filename);
1883 gnome_vfs_uri_unref (vfs_uri);
1885 if (gnome_vfs_get_file_info (uri,
1887 GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
1888 GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1890 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1891 mime_part = tny_platform_factory_new_mime_part
1892 (modest_runtime_get_platform_factory ());
1893 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1895 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1897 content_id = g_strdup_printf ("%d", priv->last_cid);
1898 tny_mime_part_set_content_id (mime_part, content_id);
1899 g_free (content_id);
1902 basename = g_path_get_basename (filename);
1903 tny_mime_part_set_filename (mime_part, basename);
1906 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1907 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1909 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1910 gtk_widget_show_all (priv->attachments_caption);
1911 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1917 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1920 ModestMsgEditWindowPrivate *priv;
1921 gboolean clean_list = FALSE;
1923 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1924 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1926 if (att_list == NULL) {
1927 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1931 if (att_list == NULL) {
1932 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1934 GtkWidget *confirmation_dialog = NULL;
1935 gboolean dialog_response;
1937 gchar *message = NULL;
1938 const gchar *filename = NULL;
1940 if (att_list->next == NULL) {
1941 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1945 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1946 att_list->next == NULL), filename);
1947 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1949 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1950 gtk_widget_destroy (confirmation_dialog);
1951 if (!dialog_response) {
1953 g_list_free (att_list);
1956 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1958 for (node = att_list; node != NULL; node = g_list_next (node)) {
1959 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1960 const gchar *att_id;
1961 priv->attachments = g_list_remove (priv->attachments, mime_part);
1963 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1965 if (priv->attachments == NULL)
1966 gtk_widget_hide (priv->attachments_caption);
1967 att_id = tny_mime_part_get_content_id (mime_part);
1969 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1971 g_object_unref (mime_part);
1972 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1977 g_list_free (att_list);
1981 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1984 ModestMsgEditWindowPrivate *priv;
1985 GdkColor *new_color;
1986 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1988 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1989 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1992 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1994 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1996 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1998 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2003 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2006 ModestMsgEditWindowPrivate *priv;
2007 gint new_size_index;
2008 ModestMsgEditWindow *window;
2011 window = MODEST_MSG_EDIT_WINDOW (userdata);
2012 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2013 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2015 if (gtk_check_menu_item_get_active (menu_item)) {
2017 WPTextBufferFormat format;
2019 memset (&format, 0, sizeof (format));
2020 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2022 label = gtk_bin_get_child (GTK_BIN (menu_item));
2024 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2025 format.cs.font_size = TRUE;
2026 format.cs.text_position = TRUE;
2027 format.cs.font = TRUE;
2028 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2029 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2031 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2032 (gpointer) wp_get_font_size_index (new_size_index, 12)))
2033 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2035 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2036 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2037 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2043 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2046 ModestMsgEditWindowPrivate *priv;
2047 gint new_font_index;
2048 ModestMsgEditWindow *window;
2051 window = MODEST_MSG_EDIT_WINDOW (userdata);
2052 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2053 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2055 if (gtk_check_menu_item_get_active (menu_item)) {
2058 label = gtk_bin_get_child (GTK_BIN (menu_item));
2060 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2062 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2063 (gpointer) new_font_index))
2064 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2066 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2067 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2068 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2074 modest_msg_edit_window_set_zoom (ModestWindow *window,
2077 ModestMsgEditWindowPrivate *priv;
2078 ModestWindowPrivate *parent_priv;
2079 GtkRadioAction *zoom_radio_action;
2081 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2083 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2084 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2085 priv->zoom_level = zoom;
2086 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom*DEFAULT_FONT_SCALE);
2088 /* Zoom level menu options should be updated with the current zoom level */
2089 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2090 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2091 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2092 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2093 /* FIXME: Not availible before Gtk 2.10 */
2095 gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
2100 modest_msg_edit_window_get_zoom (ModestWindow *window)
2102 ModestMsgEditWindowPrivate *priv;
2104 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
2106 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2107 return priv->zoom_level;
2111 zoom_allowed (ModestMsgEditWindow *window)
2115 focus = gtk_window_get_focus (GTK_WINDOW (window));
2116 return (focus != NULL && WP_IS_TEXT_VIEW (focus));
2120 modest_msg_edit_window_zoom_plus (ModestWindow *window)
2122 ModestWindowPrivate *parent_priv;
2123 GtkRadioAction *zoom_radio_action;
2124 GSList *group, *node;
2126 /* First we check if the text view is focused. If not, zooming is not allowed */
2127 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2128 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2132 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2133 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2134 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2136 group = gtk_radio_action_get_group (zoom_radio_action);
2138 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
2139 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
2143 for (node = group; node != NULL; node = g_slist_next (node)) {
2144 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
2145 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
2153 modest_msg_edit_window_zoom_minus (ModestWindow *window)
2155 ModestWindowPrivate *parent_priv;
2156 GtkRadioAction *zoom_radio_action;
2157 GSList *group, *node;
2159 /* First we check if the text view is focused. If not, zooming is not allowed */
2160 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2161 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2165 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2166 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2167 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2169 group = gtk_radio_action_get_group (zoom_radio_action);
2171 for (node = group; node != NULL; node = g_slist_next (node)) {
2172 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
2173 if (node->next != NULL) {
2174 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
2177 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
2185 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2187 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2188 ModestWindowPrivate *parent_priv;
2189 ModestWindowMgr *mgr;
2190 gboolean is_fullscreen;
2191 GtkAction *fs_toggle_action;
2194 mgr = modest_runtime_get_window_mgr ();
2195 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2197 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2199 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2200 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2201 if (is_fullscreen != active)
2202 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2210 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2213 ModestMsgEditWindowPrivate *priv = NULL;
2214 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2216 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2217 if (!priv->update_caption_visibility)
2220 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2222 gtk_widget_show (priv->cc_caption);
2224 gtk_widget_hide (priv->cc_caption);
2226 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2230 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2233 ModestMsgEditWindowPrivate *priv = NULL;
2234 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2236 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2237 if (!priv->update_caption_visibility)
2240 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2242 gtk_widget_show (priv->bcc_caption);
2244 gtk_widget_hide (priv->bcc_caption);
2246 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2250 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2251 ModestRecptEditor *editor)
2253 ModestMsgEditWindowPrivate *priv;
2255 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2256 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2257 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2259 if (editor == NULL) {
2260 GtkWidget *view_focus;
2261 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2263 /* This code should be kept in sync with ModestRecptEditor. The
2264 textview inside the recpt editor is the one that really gets the
2265 focus. As it's inside a scrolled window, and this one inside the
2266 hbox recpt editor inherits from, we'll need to go up in the
2267 hierarchy to know if the text view is part of the recpt editor
2268 or if it's a different text entry */
2270 if (gtk_widget_get_parent (view_focus)) {
2271 GtkWidget *first_parent;
2273 first_parent = gtk_widget_get_parent (view_focus);
2274 if (gtk_widget_get_parent (first_parent) &&
2275 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2276 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2281 editor = MODEST_RECPT_EDITOR (priv->to_field);
2285 modest_address_book_select_addresses (editor);
2290 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2292 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2294 modest_msg_edit_window_open_addressbook (window, NULL);
2298 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2299 gboolean show_toolbar)
2301 ModestWindowPrivate *parent_priv;
2302 const gchar *action_name;
2305 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2306 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2308 /* We can not just use the code of
2309 modest_msg_edit_window_setup_toolbar because it has a
2310 mixture of both initialization and creation code. */
2312 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2314 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2316 /* Update also the actions (to update the toggles in the
2317 menus), we have to do it manually because some other window
2318 of the same time could have changed it (remember that the
2319 toolbar fullscreen mode is shared by all the windows of the
2321 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2322 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2324 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2326 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2327 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2333 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2334 TnyHeaderFlags priority_flags)
2336 ModestMsgEditWindowPrivate *priv;
2337 ModestWindowPrivate *parent_priv;
2339 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2341 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2342 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2343 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2345 if (priv->priority_flags != priority_flags) {
2346 GtkAction *priority_action = NULL;
2348 priv->priority_flags = priority_flags;
2350 switch (priority_flags) {
2351 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2352 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2353 gtk_widget_show (priv->priority_icon);
2354 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2355 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2357 case TNY_HEADER_FLAG_LOW_PRIORITY:
2358 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2359 gtk_widget_show (priv->priority_icon);
2360 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2361 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2364 gtk_widget_hide (priv->priority_icon);
2365 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2366 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2369 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2370 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2375 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2378 ModestMsgEditWindowPrivate *priv;
2379 ModestWindowPrivate *parent_priv;
2380 gint current_format;
2382 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2384 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2385 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2387 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2388 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2390 if (current_format != file_format) {
2391 switch (file_format) {
2392 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2393 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2395 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2399 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2400 response = gtk_dialog_run (GTK_DIALOG (dialog));
2401 gtk_widget_destroy (dialog);
2402 if (response == GTK_RESPONSE_OK) {
2403 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2405 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2406 modest_maemo_toggle_action_set_active_block_notify (action, TRUE);
2411 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2416 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2419 ModestMsgEditWindowPrivate *priv;
2420 WPTextBufferFormat oldfmt, fmt;
2421 gint old_position = 0;
2425 GdkColor *color = NULL;
2426 gboolean bold, bold_set, italic, italic_set;
2427 gboolean underline, underline_set;
2428 gboolean strikethrough, strikethrough_set;
2429 gboolean position_set;
2430 gboolean font_size_set, font_set, color_set;
2433 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2434 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2436 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2438 /* First we get the currently selected font information */
2439 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2440 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2442 switch (oldfmt.text_position) {
2443 case TEXT_POSITION_NORMAL:
2446 case TEXT_POSITION_SUPERSCRIPT:
2454 g_object_set (G_OBJECT (dialog),
2455 "bold", oldfmt.bold != FALSE,
2456 "bold-set", !oldfmt.cs.bold,
2457 "underline", oldfmt.underline != FALSE,
2458 "underline-set", !oldfmt.cs.underline,
2459 "italic", oldfmt.italic != FALSE,
2460 "italic-set", !oldfmt.cs.italic,
2461 "strikethrough", oldfmt.strikethrough != FALSE,
2462 "strikethrough-set", !oldfmt.cs.strikethrough,
2463 "color", &oldfmt.color,
2464 "color-set", !oldfmt.cs.color,
2465 "size", wp_font_size[oldfmt.font_size],
2466 "size-set", !oldfmt.cs.font_size,
2467 "position", old_position,
2468 "position-set", !oldfmt.cs.text_position,
2469 "family", wp_get_font_name (oldfmt.font),
2470 "family-set", !oldfmt.cs.font,
2473 gtk_widget_show_all (dialog);
2474 response = gtk_dialog_run (GTK_DIALOG (dialog));
2475 if (response == GTK_RESPONSE_OK) {
2477 g_object_get( dialog,
2479 "bold-set", &bold_set,
2480 "underline", &underline,
2481 "underline-set", &underline_set,
2483 "italic-set", &italic_set,
2484 "strikethrough", &strikethrough,
2485 "strikethrough-set", &strikethrough_set,
2487 "color-set", &color_set,
2489 "size-set", &font_size_set,
2490 "family", &font_name,
2491 "family-set", &font_set,
2492 "position", &position,
2493 "position-set", &position_set,
2498 if (response == GTK_RESPONSE_OK) {
2499 memset(&fmt, 0, sizeof(fmt));
2505 fmt.italic = italic;
2506 fmt.cs.italic = TRUE;
2508 if (underline_set) {
2509 fmt.underline = underline;
2510 fmt.cs.underline = TRUE;
2512 if (strikethrough_set) {
2513 fmt.strikethrough = strikethrough;
2514 fmt.cs.strikethrough = TRUE;
2519 ? TEXT_POSITION_NORMAL
2520 : ( ( position == 1 )
2521 ? TEXT_POSITION_SUPERSCRIPT
2522 : TEXT_POSITION_SUBSCRIPT );
2523 fmt.cs.text_position = TRUE;
2527 fmt.cs.color = TRUE;
2530 fmt.font = wp_get_font_index(font_name,
2535 if (font_size_set) {
2536 fmt.font_size = wp_get_font_size_index(
2537 font_size, DEFAULT_FONT_SIZE);
2538 fmt.cs.font_size = TRUE;
2540 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2541 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2543 gtk_widget_destroy (dialog);
2545 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2549 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2551 ModestMsgEditWindowPrivate *priv;
2553 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2554 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2556 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2558 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2563 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2565 ModestMsgEditWindowPrivate *priv;
2567 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2568 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2570 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2572 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2577 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2579 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2581 priv->can_undo = can_undo;
2585 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2587 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2589 priv->can_redo = can_redo;
2593 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2595 ModestMsgEditWindowPrivate *priv;
2596 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2597 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2599 return priv->can_undo;
2603 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2605 ModestMsgEditWindowPrivate *priv;
2606 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2607 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2609 return priv->can_redo;
2614 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2617 GtkTextIter match_start, match_end;
2619 if (image_id == NULL)
2622 gtk_text_buffer_get_start_iter (buffer, &iter);
2624 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2625 GSList *tags = gtk_text_iter_get_tags (&match_start);
2627 for (node = tags; node != NULL; node = g_slist_next (node)) {
2628 GtkTextTag *tag = (GtkTextTag *) node->data;
2629 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2630 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2631 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2633 offset = gtk_text_iter_get_offset (&match_start);
2634 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2635 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2639 gtk_text_iter_forward_char (&iter);
2644 message_is_empty (ModestMsgEditWindow *window)
2646 ModestMsgEditWindowPrivate *priv = NULL;
2648 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2649 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2651 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
2652 * so we can ignore markup.
2654 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
2657 count = gtk_text_buffer_get_char_count (buf);
2663 msg_body_focus (GtkWidget *focus,
2664 GdkEventFocus *event,
2668 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
2673 recpt_field_changed (GtkTextBuffer *buffer,
2674 ModestMsgEditWindow *editor)
2676 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
2680 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
2682 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
2686 reset_modified (ModestMsgEditWindow *editor)
2688 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2689 GtkTextBuffer *buffer;
2691 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2692 gtk_text_buffer_set_modified (buffer, FALSE);
2693 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2694 gtk_text_buffer_set_modified (buffer, FALSE);
2695 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2696 gtk_text_buffer_set_modified (buffer, FALSE);
2697 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2701 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2703 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2704 GtkTextBuffer *buffer;
2706 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2707 if (gtk_text_buffer_get_modified (buffer))
2709 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2710 if (gtk_text_buffer_get_modified (buffer))
2712 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2713 if (gtk_text_buffer_get_modified (buffer))
2715 if (gtk_text_buffer_get_modified (priv->text_buffer))
2725 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
2727 ModestMsgEditWindowPrivate *priv = NULL;
2729 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2730 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2732 /* check if there's no recipient added */
2733 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2734 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2735 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2736 /* no recipient contents, then select contacts */
2737 modest_msg_edit_window_open_addressbook (window, NULL);
2741 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
2742 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2745 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
2746 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
2749 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
2750 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
2754 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
2755 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
2756 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2763 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2764 ModestMsgEditWindow *window)
2766 modest_msg_edit_window_offer_attach_file (window);
2770 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
2772 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
2774 return priv->clipboard_text;
2778 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2780 ModestMsgEditWindow *window)
2782 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2783 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2785 if (!GTK_WIDGET_VISIBLE (window))
2788 text = gtk_clipboard_wait_for_text (selection_clipboard);
2790 if (priv->clipboard_text != NULL) {
2791 g_free (priv->clipboard_text);
2793 priv->clipboard_text = text;
2795 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), "ModestClipboardDimmingRules");
2798 subject_field_move_cursor (GtkEntry *entry,
2799 GtkMovementStep step,
2804 if (!GTK_WIDGET_VISIBLE (window))
2807 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), "ModestClipboardDimmingRules");
2811 update_window_title (ModestMsgEditWindow *window)
2813 ModestMsgEditWindowPrivate *priv = NULL;
2814 const gchar *subject;
2816 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2817 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2818 if (subject == NULL || subject[0] == '\0')
2819 subject = _("mail_va_new_email");
2821 gtk_window_set_title (GTK_WINDOW (window), subject);
2826 subject_field_changed (GtkEditable *editable,
2827 ModestMsgEditWindow *window)
2829 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2830 update_window_title (window);
2831 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2832 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2836 subject_field_insert_text (GtkEditable *editable,
2838 gint new_text_length,
2840 ModestMsgEditWindow *window)
2842 GString *result = g_string_new ("");
2844 gint result_len = 0;
2846 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
2847 gunichar c = g_utf8_get_char_validated (current, 8);
2848 /* Invalid unichar, stop */
2854 result = g_string_append_unichar (result, c);
2858 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
2859 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
2862 /* Prevent endless recursion */
2863 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
2864 g_signal_emit_by_name (editable, "insert-text",
2865 (gpointer) result->str, (gpointer) result->len,
2866 (gpointer) position, (gpointer) window);
2867 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
2871 g_string_free (result, TRUE);
2875 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2878 ModestMsgEditWindowPrivate *priv = NULL;
2880 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2881 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2883 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2886 gtk_widget_show_all (priv->find_toolbar);
2887 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2889 gtk_widget_hide_all (priv->find_toolbar);
2890 gtk_widget_grab_focus (priv->msg_body);
2896 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2898 GtkTextIter *match_start,
2899 GtkTextIter *match_end)
2901 GtkTextIter end_iter;
2902 gchar *str_casefold;
2905 gchar *range_casefold;
2908 gboolean result = FALSE;
2915 gtk_text_iter_forward_to_end (&end_iter);
2917 str_casefold = g_utf8_casefold (str, -1);
2918 str_chars_n = strlen (str);
2920 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2921 range_casefold = g_utf8_casefold (range_text, -1);
2922 range_chars_n = strlen (range_casefold);
2924 if (range_chars_n < str_chars_n) {
2925 g_free (str_casefold);
2926 g_free (range_text);
2927 g_free (range_casefold);
2931 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2932 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2933 if (!g_utf8_collate (range_subtext, str_casefold)) {
2934 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2936 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2937 match_start, match_end, NULL);
2938 g_free (found_text);
2940 g_free (range_subtext);
2944 g_free (str_casefold);
2945 g_free (range_text);
2946 g_free (range_casefold);
2953 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2954 ModestMsgEditWindow *window)
2956 gchar *current_search = NULL;
2957 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2959 GtkTextIter selection_start, selection_end;
2960 GtkTextIter match_start, match_end;
2961 gboolean continue_search = FALSE;
2963 if (message_is_empty (window)) {
2964 g_free (priv->last_search);
2965 priv->last_search = NULL;
2966 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
2970 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2971 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2972 g_free (current_search);
2973 g_free (priv->last_search);
2974 priv->last_search = NULL;
2975 /* Information banner about empty search */
2976 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2980 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2981 continue_search = TRUE;
2983 g_free (priv->last_search);
2984 priv->last_search = g_strdup (current_search);
2987 if (continue_search) {
2988 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2989 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2990 &match_start, &match_end);
2992 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2994 GtkTextIter buffer_start;
2995 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2996 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2997 &match_start, &match_end);
2999 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3002 /* Mark as selected the string found in search */
3004 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3005 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3007 g_free (priv->last_search);
3008 priv->last_search = NULL;
3010 g_free (current_search);
3014 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3015 ModestMsgEditWindow *window)
3017 GtkToggleAction *toggle;
3018 ModestWindowPrivate *parent_priv;
3019 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3021 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3022 gtk_toggle_action_set_active (toggle, FALSE);
3026 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3028 ModestMsgEditWindowPrivate *priv;
3030 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3035 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3038 ModestMsgEditWindowPrivate *priv;
3040 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3046 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3049 ModestMsgEditWindowPrivate *priv;
3050 TnyHeader *header = NULL;
3052 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3053 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3055 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3056 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3058 if (priv->draft_msg != NULL) {
3059 header = tny_msg_get_header (priv->draft_msg);
3060 if (TNY_IS_HEADER (header)) {
3061 modest_window_mgr_unregister_header (mgr, header);
3063 g_object_unref (priv->draft_msg);
3066 if (draft != NULL) {
3067 g_object_ref (draft);
3068 header = tny_msg_get_header (draft);
3069 if (TNY_IS_HEADER (header))
3070 modest_window_mgr_register_header (mgr, header);
3071 if (priv->msg_uid) {
3072 g_free (priv->msg_uid);
3073 priv->msg_uid = NULL;
3075 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3078 priv->draft_msg = draft;
3082 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3083 GtkTextIter *start, GtkTextIter *end,
3086 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3087 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3090 if (tag == NULL+13) return;
3091 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3092 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3093 replace_with_attachments (window, priv->attachments);
3098 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3101 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3103 g_return_if_fail (TNY_IS_MIME_PART (part));
3104 priv->attachments = g_list_prepend (priv->attachments, part);
3105 g_object_ref (part);
3106 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part);
3107 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3108 gtk_widget_show_all (priv->attachments_caption);
3109 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3113 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3115 ModestMsgEditWindowPrivate *priv;
3117 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3118 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3120 return priv->msg_uid;
3124 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3125 ModestMsgEditWindowWidgetType widget_type)
3127 ModestMsgEditWindowPrivate *priv;
3129 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3130 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3132 switch (widget_type) {
3133 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3134 return priv->msg_body;
3136 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3137 return priv->to_field;
3139 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3140 return priv->cc_field;
3142 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3143 return priv->bcc_field;
3145 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3146 return priv->subject_field;
3148 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3149 return priv->attachments_view;