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>
38 #include <tny-camel-mem-stream.h>
39 #include <modest-account-protocol.h>
43 #include <modest-account-mgr.h>
44 #include <modest-account-mgr-helpers.h>
46 #include <widgets/modest-msg-edit-window.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <modest-wp-text-view.h>
65 #include <wptextbuffer.h>
66 #include <modest-scrollable.h>
67 #include <modest-isearch-toolbar.h>
68 #include "modest-msg-edit-window-ui-dimming.h"
70 #include "widgets/modest-msg-edit-window-ui.h"
71 #include <libgnomevfs/gnome-vfs-mime.h>
72 #include <modest-utils.h>
73 #include <modest-ui-constants.h>
74 #include <modest-toolkit-utils.h>
76 #ifdef MODEST_USE_CALENDAR_WIDGETS
77 #include <calendar-ui-widgets.h>
79 #ifdef MODEST_TOOLKIT_HILDON2
80 #include <hildon/hildon.h>
81 #include "modest-maemo-utils.h"
82 #include "modest-hildon-includes.h"
83 #include "modest-color-button.h"
86 #define DEFAULT_MAIN_VBOX_SPACING 0
87 #define SUBJECT_MAX_LENGTH 1000
88 #define IMAGE_MAX_WIDTH 560
89 #ifdef MODEST_TOOLKIT_HILDON2
90 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
91 #define DEFAULT_FONT_SCALE 1.5
92 #define DEFAULT_FONT_SIZE 3
93 #define DEFAULT_FONT 2
95 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
96 #define DEFAULT_FONT_SCALE 1.0
97 #define DEFAULT_FONT_SIZE 2
98 #define DEFAULT_FONT 2
100 #define ATTACHMENT_BUTTON_WIDTH 118
101 #define MAX_FROM_VALUE 36
102 #define MAX_BODY_LENGTH 128*1024
103 #define MAX_BODY_LINES 2048
105 static gboolean is_wp_text_buffer_started = FALSE;
107 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
108 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
109 static void modest_msg_edit_window_finalize (GObject *obj);
111 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
112 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
113 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
115 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
116 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
117 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
118 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
119 GtkTextIter *start, GtkTextIter *end,
121 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
122 static void body_insert_text (GtkTextBuffer *buffer,
123 GtkTextIter *location,
126 ModestMsgEditWindow *window);
127 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
128 static void subject_field_insert_text (GtkEditable *editable,
130 gint new_text_length,
132 ModestMsgEditWindow *window);
133 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
135 #ifdef MODEST_TOOLKIT_HILDON2
136 static void font_face_clicked (GtkToolButton *button,
137 ModestMsgEditWindow *window);
139 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
142 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
144 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
145 ModestRecptEditor *editor);
146 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
147 ModestMsgEditWindow *window);
149 /* ModestWindow methods implementation */
150 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
151 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
152 gboolean show_toolbar);
153 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
155 ModestMsgEditWindow *window);
156 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
157 static void subject_field_move_cursor (GtkEntry *entry,
158 GtkMovementStep step,
162 static void update_window_title (ModestMsgEditWindow *window);
165 static void modest_msg_edit_window_isearch_toolbar_search (GtkWidget *widget,
166 ModestMsgEditWindow *window);
167 static void modest_msg_edit_window_isearch_toolbar_close (GtkWidget *widget,
168 ModestMsgEditWindow *window);
169 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
171 GtkTextIter *match_start,
172 GtkTextIter *match_end);
174 static void remove_tags (WPTextBuffer *buffer);
176 static void on_account_removed (TnyAccountStore *account_store,
180 static void init_window (ModestMsgEditWindow *obj);
182 gboolean scroll_drag_timeout (gpointer userdata);
183 static void correct_scroll (ModestMsgEditWindow *w);
184 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
185 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
186 ModestMsgEditWindow *userdata);
187 static void text_buffer_mark_set (GtkTextBuffer *buffer,
190 ModestMsgEditWindow *userdata);
191 static void on_show_toolbar_button_toggled (GtkWidget *button,
192 ModestMsgEditWindow *window);
193 static void on_message_settings (GtkAction *action,
194 ModestMsgEditWindow *window);
195 static void setup_menu (ModestMsgEditWindow *self);
197 static void from_field_changed (GtkWidget *button,
198 ModestMsgEditWindow *self);
199 static void font_size_clicked (GtkToolButton *button,
200 ModestMsgEditWindow *window);
201 static void update_signature (ModestMsgEditWindow *self,
202 const gchar *old_account,
203 const gchar *new_account);
204 static void update_branding (ModestMsgEditWindow *self,
205 const gchar *new_account);
206 static GtkWidget *_create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
207 const gchar *label, GtkWidget *control);
208 static void max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref);
209 static void DEBUG_BUFFER (WPTextBuffer *buffer)
213 g_debug ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
215 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
216 while (!gtk_text_iter_is_end (&iter)) {
217 GString *output = g_string_new ("");
218 GSList *toggled_tags;
221 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
222 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
223 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
224 GtkTextTag *tag = (GtkTextTag *) node->data;
226 g_object_get (G_OBJECT (tag), "name", &name, NULL);
227 output = g_string_append (output, name);
228 g_string_append (output, " ");
230 output = g_string_append (output, "] OPENED [ ");
231 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
232 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
233 GtkTextTag *tag = (GtkTextTag *) node->data;
235 g_object_get (G_OBJECT (tag), "name", &name, NULL);
236 output = g_string_append (output, name);
237 g_string_append (output, " ");
239 output = g_string_append (output, "]\n");
240 g_debug ("%s", output->str);
241 g_string_free (output, TRUE);
242 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
244 g_debug ("END BUFFER");
248 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
249 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
253 /* static gboolean */
254 /* on_key_pressed (GtkWidget *self, */
255 /* GdkEventKey *event, */
256 /* gpointer user_data); */
258 /* list my signals */
265 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
266 struct _ModestMsgEditWindowPrivate {
268 GtkWidget *header_box;
270 ModestPairList *from_field_protos;
271 GtkWidget *from_field;
272 gchar *last_from_account;
273 gchar *original_account_name;
278 gchar *original_mailbox;
282 GtkWidget *bcc_field;
283 GtkWidget *subject_field;
284 GtkWidget *attachments_view;
285 GtkWidget *priority_icon;
286 GtkWidget *subject_box;
287 GtkWidget *send_button;
289 GtkWidget *cc_caption;
290 GtkWidget *bcc_caption;
291 gboolean update_caption_visibility;
292 GtkWidget *attachments_caption;
294 GtkTextBuffer *text_buffer;
296 GtkWidget *font_size_toolitem;
297 GtkWidget *font_face_toolitem;
298 GtkWidget *font_color_button;
299 GtkWidget *font_color_toolitem;
300 GSList *font_items_group;
301 GtkTreeModel *faces_model;
302 gint current_face_index;
303 GtkWidget *font_tool_button_label;
304 GtkTreeModel *sizes_model;
305 gint current_size_index;
306 GtkWidget *size_tool_button_label;
308 GtkWidget *isearch_toolbar;
311 GtkWidget *font_dialog;
313 GtkWidget *scrollable;
314 guint correct_scroll_idle;
315 guint scroll_drag_timeout_id;
319 TnyList *attachments;
324 TnyHeaderFlags priority_flags;
326 gboolean can_undo, can_redo;
327 gulong clipboard_change_handler_id;
328 gulong default_clipboard_change_handler_id;
329 gulong account_removed_handler_id;
330 guint clipboard_owner_idle;
331 gchar *clipboard_text;
340 GtkWidget *cc_button;
341 GtkWidget *bcc_button;
342 GtkWidget *show_toolbar_button;
344 GtkWidget *max_chars_banner;
346 GtkWidget *brand_icon;
347 GtkWidget *brand_label;
348 GtkWidget *brand_container;
351 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
352 MODEST_TYPE_MSG_EDIT_WINDOW, \
353 ModestMsgEditWindowPrivate))
355 static GtkWindowClass *parent_class = NULL;
357 /* uncomment the following if you have defined any signals */
358 /* static guint signals[LAST_SIGNAL] = {0}; */
361 modest_msg_edit_window_get_type (void)
363 static GType my_type = 0;
365 static const GTypeInfo my_info = {
366 sizeof(ModestMsgEditWindowClass),
367 NULL, /* base init */
368 NULL, /* base finalize */
369 (GClassInitFunc) modest_msg_edit_window_class_init,
370 NULL, /* class finalize */
371 NULL, /* class data */
372 sizeof(ModestMsgEditWindow),
374 (GInstanceInitFunc) modest_msg_edit_window_init,
377 my_type = g_type_register_static (
378 #ifdef MODEST_TOOLKIT_HILDON2
379 MODEST_TYPE_HILDON2_WINDOW,
381 MODEST_TYPE_SHELL_WINDOW,
383 "ModestMsgEditWindow",
391 save_state (ModestWindow *self)
393 modest_widget_memory_save (modest_runtime_get_conf(),
394 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
399 restore_settings (ModestMsgEditWindow *self)
401 ModestConf *conf = NULL;
403 conf = modest_runtime_get_conf ();
405 /* Dim at start clipboard actions */
406 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
411 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
413 GObjectClass *gobject_class;
414 ModestWindowClass *modest_window_class;
415 gobject_class = (GObjectClass*) klass;
416 modest_window_class = (ModestWindowClass*) klass;
418 parent_class = g_type_class_peek_parent (klass);
419 gobject_class->finalize = modest_msg_edit_window_finalize;
421 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
422 modest_window_class->save_state_func = save_state;
423 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
425 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
429 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
431 ModestMsgEditWindowPrivate *priv;
432 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
434 priv->msg_body = NULL;
435 priv->from_field = NULL;
436 priv->to_field = NULL;
437 priv->cc_field = NULL;
438 priv->bcc_field = NULL;
439 priv->subject_field = NULL;
440 priv->attachments = TNY_LIST (tny_simple_list_new ());
441 priv->images = TNY_LIST (tny_simple_list_new ());
442 priv->images_size = 0;
443 priv->images_count = 0;
446 priv->cc_caption = NULL;
447 priv->bcc_caption = NULL;
448 priv->update_caption_visibility = FALSE;
450 priv->priority_flags = 0;
452 priv->isearch_toolbar = NULL;
453 priv->last_search = NULL;
455 priv->draft_msg = NULL;
456 priv->outbox_msg = NULL;
457 priv->msg_uid = NULL;
459 priv->can_undo = FALSE;
460 priv->can_redo = FALSE;
461 priv->clipboard_change_handler_id = 0;
462 priv->default_clipboard_change_handler_id = 0;
463 priv->account_removed_handler_id = 0;
464 priv->clipboard_owner_idle = 0;
465 priv->clipboard_text = NULL;
468 priv->scroll_drag_timeout_id = 0;
469 priv->correct_scroll_idle = 0;
470 priv->last_upper = 0.0;
472 priv->font_dialog = NULL;
473 priv->app_menu = NULL;
475 priv->references = NULL;
476 priv->in_reply_to = NULL;
477 priv->max_chars_banner = NULL;
479 if (!is_wp_text_buffer_started) {
480 is_wp_text_buffer_started = TRUE;
481 wp_text_buffer_library_init ();
485 #ifdef MODEST_TOOLKIT_HILDON2
486 hildon_program_add_window (hildon_program_get_instance(),
492 multimailbox_get_default_mailbox (const gchar *account_name)
494 gchar *transport_account;
495 gchar *result = NULL;
497 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
499 TNY_ACCOUNT_TYPE_TRANSPORT);
500 if (transport_account) {
502 ModestProtocolRegistry *registry;
504 registry = modest_runtime_get_protocol_registry ();
506 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
507 MODEST_ACCOUNT_PROTO, TRUE);
509 ModestProtocol *protocol =
510 modest_protocol_registry_get_protocol_by_name (registry,
511 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
513 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
514 ModestPairList *pair_list;
516 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
519 ModestPair *pair = (ModestPair *) pair_list->data;
520 result = g_strdup ((const gchar *) pair->first);
521 modest_pair_list_free (pair_list);
532 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
534 static ModestPairList*
535 get_transports (void)
537 GSList *transports = NULL;
539 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
540 GSList *accounts = modest_account_mgr_account_names (account_mgr,
541 TRUE /* only enabled accounts. */);
543 GSList *cursor = accounts;
545 gchar *account_name = cursor->data;
548 gchar *transport_account;
549 gboolean multi_mailbox = FALSE;
550 ModestProtocol *protocol = NULL;
552 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
554 transport_account = modest_account_mgr_get_server_account_name
555 (modest_runtime_get_account_mgr (),
557 TNY_ACCOUNT_TYPE_TRANSPORT);
558 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
559 ModestPairList *pair_list;
560 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
563 transports = g_slist_concat (transports, pair_list);
564 multi_mailbox = TRUE;
569 if (!multi_mailbox) {
570 gchar *from_string = NULL;
572 from_string = modest_account_mgr_get_from_string (account_mgr,
574 if (from_string && account_name) {
575 gchar *name = account_name;
576 ModestPair *pair = modest_pair_new ((gpointer) name,
577 (gpointer) from_string , TRUE);
578 transports = g_slist_prepend (transports, pair);
583 cursor = cursor->next;
585 g_slist_free (accounts); /* only free the accounts, not the elements,
586 * because they are used in the pairlist */
590 static void window_focus (GtkWindow *window,
594 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
598 scroll_drag_timeout (gpointer userdata)
600 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
601 ModestMsgEditWindowPrivate *priv;
603 /* It could happen that the window was already closed */
604 if (!GTK_WIDGET_VISIBLE (win))
607 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
609 correct_scroll_without_drag_check (win, TRUE);
611 priv->scroll_drag_timeout_id = 0;
617 correct_scroll_without_drag_check_idle (gpointer userdata)
619 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
620 ModestMsgEditWindowPrivate *priv;
622 GdkRectangle rectangle;
623 gint offset_min, offset_max;
627 /* It could happen that the window was already closed */
628 if (!GTK_WIDGET_VISIBLE (w))
631 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
633 insert = gtk_text_buffer_get_insert (priv->text_buffer);
634 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
636 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
637 offset_min = priv->msg_body->allocation.y + rectangle.y;
638 offset_max = offset_min + rectangle.height;
640 vadj = modest_scrollable_get_vadjustment (MODEST_SCROLLABLE (priv->scrollable));
641 offset_min = MAX (offset_min - 48, 0);
642 offset_max = MIN (offset_max + 48, vadj->upper);
644 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
646 priv->correct_scroll_idle = 0;
651 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
653 ModestMsgEditWindowPrivate *priv;
655 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
657 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
660 if (priv->correct_scroll_idle > 0) {
664 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
665 (GSourceFunc) correct_scroll_without_drag_check_idle,
671 correct_scroll (ModestMsgEditWindow *w)
673 ModestMsgEditWindowPrivate *priv;
675 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
676 if (gtk_grab_get_current () == priv->msg_body) {
677 if (priv->scroll_drag_timeout_id == 0) {
678 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
680 (GSourceFunc) scroll_drag_timeout,
687 correct_scroll_without_drag_check (w, TRUE);
691 text_buffer_end_user_action (GtkTextBuffer *buffer,
692 ModestMsgEditWindow *userdata)
695 correct_scroll (userdata);
699 text_buffer_mark_set (GtkTextBuffer *buffer,
702 ModestMsgEditWindow *userdata)
704 gtk_text_buffer_begin_user_action (buffer);
705 gtk_text_buffer_end_user_action (buffer);
709 cut_clipboard_check (GtkTextView *text_view,
712 GtkTextBuffer *buffer;
714 buffer = gtk_text_view_get_buffer (text_view);
715 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
716 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
721 copy_clipboard_check (GtkTextView *text_view,
724 GtkTextBuffer *buffer;
726 buffer = gtk_text_view_get_buffer (text_view);
727 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
728 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
733 attachment_deleted (ModestAttachmentsView *attachments_view,
736 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
741 body_size_request (GtkWidget *body,
745 /* Make sure the body always get at least 70 pixels */
746 if (req->height < 70)
751 connect_signals (ModestMsgEditWindow *obj)
753 ModestMsgEditWindowPrivate *priv;
755 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
757 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
758 G_CALLBACK (text_buffer_refresh_attributes), obj);
759 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
760 G_CALLBACK (text_buffer_can_undo), obj);
761 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
762 G_CALLBACK (text_buffer_can_redo), obj);
763 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
764 G_CALLBACK (body_changed), obj);
765 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
766 G_CALLBACK (body_insert_text), obj);
767 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
768 G_CALLBACK (body_changed), obj);
769 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
770 G_CALLBACK (text_buffer_end_user_action), obj);
771 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
772 G_CALLBACK (text_buffer_mark_set), obj);
773 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
774 G_CALLBACK (text_buffer_apply_tag), obj);
775 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
776 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
777 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
778 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
779 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
780 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
782 g_signal_connect (G_OBJECT (priv->send_button), "clicked",
783 G_CALLBACK (modest_ui_actions_on_send), obj);
785 if (GTK_IS_COMBO_BOX (priv->from_field)) {
786 g_signal_connect (G_OBJECT (priv->from_field), "changed",
787 G_CALLBACK (from_field_changed), obj);
789 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
790 G_CALLBACK (from_field_changed), obj);
793 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
794 G_CALLBACK (msg_body_focus), obj);
795 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
796 G_CALLBACK (msg_body_focus), obj);
797 g_signal_connect (G_OBJECT (priv->msg_body), "size-request",
798 G_CALLBACK (body_size_request), obj);
799 if (GTK_IS_WINDOW (obj)) {
800 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
802 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
803 "changed", G_CALLBACK (recpt_field_changed), obj);
804 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
805 "changed", G_CALLBACK (recpt_field_changed), obj);
806 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
807 "changed", G_CALLBACK (recpt_field_changed), obj);
808 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
809 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
810 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
812 g_signal_connect (G_OBJECT (priv->isearch_toolbar), "isearch-search",
813 G_CALLBACK (modest_msg_edit_window_isearch_toolbar_search), obj);
814 g_signal_connect (G_OBJECT (priv->isearch_toolbar), "isearch-close",
815 G_CALLBACK (modest_msg_edit_window_isearch_toolbar_close), obj);
817 priv->clipboard_change_handler_id =
818 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
819 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
820 priv->default_clipboard_change_handler_id =
821 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
822 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
824 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
825 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
826 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
830 init_wp_text_view_style ()
832 static gboolean initialized = FALSE;
835 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
841 init_window (ModestMsgEditWindow *obj)
843 GtkWidget *to_caption, *subject_caption;
844 GtkWidget *main_vbox;
845 ModestMsgEditWindowPrivate *priv;
846 GtkActionGroup *action_group;
847 ModestWindowPrivate *parent_priv;
848 GError *error = NULL;
850 GtkSizeGroup *title_size_group;
851 GtkSizeGroup *value_size_group;
852 GtkWidget *window_box;
853 GtkWidget *window_align;
854 #if (GTK_MINOR_VERSION >= 10)
855 GdkAtom deserialize_type;
857 GtkWidget *from_send_hbox;
858 GtkWidget *send_icon;
859 GtkWidget *attachments_label;
860 GtkWidget *branding_box;
861 GtkWidget *from_caption;
863 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
864 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
866 parent_priv->ui_manager = gtk_ui_manager_new();
867 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
868 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
870 /* Add common actions */
871 gtk_action_group_add_actions (action_group,
872 modest_msg_edit_action_entries,
873 G_N_ELEMENTS (modest_msg_edit_action_entries),
875 gtk_action_group_add_actions (action_group,
876 hildon2_msg_edit_action_entries,
877 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
879 gtk_action_group_add_toggle_actions (action_group,
880 modest_msg_edit_toggle_action_entries,
881 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
883 gtk_action_group_add_radio_actions (action_group,
884 modest_msg_edit_alignment_radio_action_entries,
885 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
887 G_CALLBACK (modest_ui_actions_on_change_justify),
889 gtk_action_group_add_radio_actions (action_group,
890 modest_msg_edit_priority_action_entries,
891 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
893 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
895 gtk_action_group_add_radio_actions (action_group,
896 modest_msg_edit_file_format_action_entries,
897 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
898 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
899 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
901 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
902 g_object_unref (action_group);
904 /* Load the UI definition */
905 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
908 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
909 g_clear_error (&error);
912 parent_priv->menubar = NULL;
914 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
915 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
917 /* Note: This ModestPairList* must exist for as long as the picker
918 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
919 * so it can't know how to manage its memory. */
920 priv->from_field = modest_toolkit_factory_create_selector (modest_runtime_get_toolkit_factory (),
922 modest_selector_set_value_max_chars (priv->from_field, MAX_FROM_VALUE);
923 if (GTK_IS_COMBO_BOX (priv->from_field)) {
924 from_caption = modest_toolkit_utils_create_captioned (title_size_group, NULL,
925 _("mail_va_from"), FALSE,
927 gtk_widget_show (from_caption);
929 #ifdef MODEST_TOOLKIT_HILDON2
930 modest_toolkit_utils_set_hbutton_layout (title_size_group, NULL,
931 _("mail_va_from"), priv->from_field);
932 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
933 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
934 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
935 from_caption = priv->from_field;
939 priv->to_field = modest_recpt_editor_new ();
940 priv->cc_field = modest_recpt_editor_new ();
941 priv->bcc_field = modest_recpt_editor_new ();
942 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
943 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
944 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
945 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
946 priv->priority_icon = gtk_image_new ();
947 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
948 priv->subject_field = modest_toolkit_factory_create_entry (modest_runtime_get_toolkit_factory ());
949 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
950 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
951 modest_entry_set_hint (priv->subject_field, _("mail_va_no_subject"));
953 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
954 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
956 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
957 priv->attachments_view = modest_attachments_view_new (NULL);
958 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
959 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
961 priv->header_box = gtk_vbox_new (FALSE, 0);
963 to_caption = _create_addressbook_box
964 (title_size_group, value_size_group,
965 _("mail_va_to"), priv->to_field);
966 priv->cc_caption = _create_addressbook_box
967 (title_size_group, value_size_group,
968 _("mail_va_cc"), priv->cc_field);
969 priv->bcc_caption = _create_addressbook_box
970 (title_size_group, value_size_group,
971 _("mail_va_hotfix1"), priv->bcc_field);
972 subject_caption = modest_toolkit_utils_create_captioned (title_size_group, value_size_group,
973 _("mail_va_subject"), FALSE, priv->subject_box);
974 priv->attachments_caption = modest_toolkit_utils_create_captioned_with_size_type (NULL, NULL,
975 _("mail_va_attachment"),
977 priv->attachments_view,
978 #ifdef MODEST_TOOLKIT_HILDON2
979 HILDON_SIZE_AUTO_WIDTH |
980 HILDON_SIZE_AUTO_HEIGHT
985 attachments_label = modest_toolkit_utils_captioned_get_label_widget (priv->attachments_caption);
987 hildon_gtk_widget_set_theme_size (attachments_label, HILDON_SIZE_AUTO_HEIGHT);
991 #ifdef MODEST_TOOLKIT_HILDON2
992 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
993 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
995 priv->send_button = gtk_button_new ();
996 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, GTK_ICON_SIZE_BUTTON);
998 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
999 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 148, -1);
1001 g_object_unref (title_size_group);
1002 g_object_unref (value_size_group);
1004 priv->brand_icon = gtk_image_new ();
1005 gtk_misc_set_alignment (GTK_MISC (priv->brand_icon), 0.5, 0.5);
1006 priv->brand_label = gtk_label_new (NULL);
1007 #ifdef MODEST_TOOLKIT_HILDON2
1008 hildon_helper_set_logical_font (priv->brand_label, "SmallSystemFont");
1010 gtk_misc_set_alignment (GTK_MISC (priv->brand_label), 0.0, 0.5);
1011 gtk_widget_set_no_show_all (priv->brand_icon, TRUE);
1012 gtk_widget_set_no_show_all (priv->brand_label, TRUE);
1014 from_send_hbox = gtk_hbox_new (FALSE, 0);
1015 gtk_box_pack_start (GTK_BOX (from_send_hbox), from_caption, TRUE, TRUE, 0);
1016 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
1018 branding_box = gtk_hbox_new (FALSE, MODEST_MARGIN_DEFAULT);
1019 gtk_widget_show (branding_box);
1020 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_label, FALSE, FALSE, 0);
1021 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_icon, FALSE, FALSE, 0);
1023 priv->brand_container = gtk_alignment_new (0.0, 0.5, 0.0, 1.0);
1024 gtk_alignment_set_padding (GTK_ALIGNMENT (priv->brand_container), 0, 0, MODEST_MARGIN_DOUBLE, 0);
1025 gtk_container_add (GTK_CONTAINER (priv->brand_container), branding_box);
1026 gtk_widget_set_no_show_all (priv->brand_container, TRUE);
1029 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
1030 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
1031 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
1032 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
1033 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
1034 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
1035 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->brand_container, FALSE, FALSE, 0);
1036 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
1038 init_wp_text_view_style ();
1040 priv->msg_body = modest_wp_text_view_new ();
1043 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
1044 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1045 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
1046 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1047 #if (GTK_MINOR_VERSION >= 10)
1048 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
1049 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
1051 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
1052 deserialize_type, TRUE);
1054 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1056 priv->isearch_toolbar = modest_toolkit_factory_create_isearch_toolbar (modest_runtime_get_toolkit_factory (),
1058 gtk_widget_set_no_show_all (priv->isearch_toolbar, TRUE);
1060 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
1062 priv->scrollable = modest_toolkit_factory_create_scrollable (modest_runtime_get_toolkit_factory ());
1064 g_object_set (G_OBJECT (priv->scrollable), "horizontal-policy", GTK_POLICY_NEVER, NULL);
1066 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
1067 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1068 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
1070 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
1071 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
1072 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
1074 modest_scrollable_add_with_viewport (MODEST_SCROLLABLE (priv->scrollable), window_align);
1075 gtk_widget_show_all (GTK_WIDGET(priv->scrollable));
1077 window_box = gtk_vbox_new (FALSE, 0);
1078 gtk_container_add (GTK_CONTAINER(obj), window_box);
1080 gtk_box_pack_start (GTK_BOX (window_box), priv->scrollable, TRUE, TRUE, 0);
1085 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
1087 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1089 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1090 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1091 priv->clipboard_change_handler_id))
1092 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1093 priv->clipboard_change_handler_id);
1094 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1095 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1096 priv->default_clipboard_change_handler_id))
1097 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1098 priv->default_clipboard_change_handler_id);
1100 if (priv->account_removed_handler_id &&
1101 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1102 priv->account_removed_handler_id))
1103 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1104 priv->account_removed_handler_id);
1108 modest_msg_edit_window_finalize (GObject *obj)
1110 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1112 if (priv->max_chars_banner) {
1113 g_object_weak_unref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, obj);
1114 priv->max_chars_banner = FALSE;
1117 /* Sanity check: shouldn't be needed, the window mgr should
1118 call this function before */
1119 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1121 if (priv->font_dialog != NULL) {
1122 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1125 if (priv->clipboard_text != NULL) {
1126 g_free (priv->clipboard_text);
1127 priv->clipboard_text = NULL;
1130 if (priv->draft_msg != NULL) {
1131 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1132 if (TNY_IS_HEADER (header)) {
1133 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1134 modest_window_mgr_unregister_header (mgr, header);
1136 g_object_unref (priv->draft_msg);
1137 priv->draft_msg = NULL;
1139 if (priv->outbox_msg != NULL) {
1140 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1141 if (TNY_IS_HEADER (header)) {
1142 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1143 modest_window_mgr_unregister_header (mgr, header);
1145 g_object_unref (priv->outbox_msg);
1146 priv->outbox_msg = NULL;
1148 if (priv->correct_scroll_idle > 0) {
1149 g_source_remove (priv->correct_scroll_idle);
1150 priv->correct_scroll_idle = 0;
1152 if (priv->scroll_drag_timeout_id > 0) {
1153 g_source_remove (priv->scroll_drag_timeout_id);
1154 priv->scroll_drag_timeout_id = 0;
1156 if (priv->clipboard_owner_idle > 0) {
1157 g_source_remove (priv->clipboard_owner_idle);
1158 priv->clipboard_owner_idle = 0;
1160 if (priv->original_account_name)
1161 g_free (priv->original_account_name);
1162 if (priv->original_mailbox)
1163 g_free (priv->original_mailbox);
1164 g_free (priv->msg_uid);
1165 g_free (priv->last_search);
1166 g_slist_free (priv->font_items_group);
1167 g_free (priv->references);
1168 g_free (priv->in_reply_to);
1169 g_object_unref (priv->attachments);
1170 g_object_unref (priv->images);
1172 /* This had to stay alive for as long as the picker that used it: */
1173 modest_pair_list_free (priv->from_field_protos);
1175 G_OBJECT_CLASS(parent_class)->finalize (obj);
1179 pixbuf_size_prepared (GdkPixbufLoader *loader,
1182 ModestMsgEditWindow *self)
1184 gint new_height, new_width;
1187 new_height = height;
1191 if (width > IMAGE_MAX_WIDTH) {
1192 new_height = height * IMAGE_MAX_WIDTH / width;
1193 new_width = IMAGE_MAX_WIDTH;
1196 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1200 pixbuf_from_stream (TnyStream *stream,
1201 const gchar *mime_type,
1202 guint64 *stream_size,
1203 ModestMsgEditWindow *self)
1205 GdkPixbufLoader *loader;
1208 GError *error = NULL;
1212 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1214 if (loader == NULL) {
1219 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1221 modest_window_show_progress (MODEST_WINDOW (self), TRUE);
1223 tny_stream_reset (TNY_STREAM (stream));
1224 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1225 unsigned char read_buffer[128];
1227 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1229 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1232 /* Allow some UI responsiveness */
1233 while (gtk_events_pending ())
1234 gtk_main_iteration ();
1236 modest_window_show_progress (MODEST_WINDOW (self), FALSE);
1238 gdk_pixbuf_loader_close (loader, &error);
1241 g_error_free (error);
1242 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1244 g_object_ref (pixbuf);
1245 g_object_unref (loader);
1250 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1251 GdkPixbuf *new_pixbuf;
1253 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1254 gdk_pixbuf_get_width (pixbuf);
1255 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1256 g_object_unref (pixbuf);
1257 pixbuf = new_pixbuf;
1261 *stream_size = size;
1267 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1269 ModestMsgEditWindowPrivate *priv;
1272 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1274 g_object_ref (self);
1275 for (iter = tny_list_create_iterator (attachments);
1276 !tny_iterator_is_done (iter);
1277 tny_iterator_next (iter)) {
1278 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1279 const gchar *cid = tny_mime_part_get_content_id (part);
1280 const gchar *mime_type = tny_mime_part_get_content_type (part);
1281 if ((cid != NULL)&&(mime_type != NULL)) {
1282 guint64 stream_size;
1283 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1284 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1287 g_object_unref (stream);
1289 if (pixbuf != NULL) {
1290 priv->images_count ++;
1291 priv->images_size += stream_size;
1292 #ifndef MODEST_HAVE_LIBWPEDITOR_PLUS
1293 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1295 g_object_unref (pixbuf);
1298 g_object_unref (part);
1300 g_object_unref (iter);
1301 g_object_unref (self);
1305 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1307 TnyMimePart *parent = NULL;
1308 const gchar *content_type = NULL;
1309 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1311 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1313 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1314 parent = g_object_ref (msg);
1315 } else if (content_type && !g_ascii_strcasecmp (content_type, "multipart/mixed")) {
1316 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1319 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1320 iter = tny_list_create_iterator (parts);
1321 while (!tny_iterator_is_done (iter)) {
1323 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1324 content_type = tny_mime_part_get_content_type (part);
1325 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1329 g_object_unref (part);
1331 tny_iterator_next (iter);
1333 g_object_unref (iter);
1334 g_object_unref (parts);
1337 if (parent != NULL) {
1338 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1341 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1342 iter = tny_list_create_iterator (parts);
1343 while (!tny_iterator_is_done (iter)) {
1345 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1346 content_type = tny_mime_part_get_content_type (part);
1347 if (content_type && g_str_has_prefix (content_type, "image/")) {
1348 tny_list_prepend (priv->images, (GObject *) part);
1350 g_object_unref (part);
1351 tny_iterator_next (iter);
1353 g_object_unref (iter);
1354 g_object_unref (parts);
1355 g_object_unref (parent);
1360 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1363 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1365 for (iter = tny_list_create_iterator (attachments) ;
1366 !tny_iterator_is_done (iter);
1367 tny_iterator_next (iter)) {
1368 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1369 const gchar *cid = tny_mime_part_get_content_id (part);
1371 char *invalid = NULL;
1372 gint int_cid = strtol (cid, &invalid, 10);
1373 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1374 priv->next_cid = int_cid + 1;
1377 g_object_unref (part);
1379 g_object_unref (iter);
1383 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1386 gchar *to, *cc, *bcc, *subject;
1388 ModestMsgEditWindowPrivate *priv;
1389 ModestWindowPrivate *parent_priv;
1391 TnyHeaderFlags priority_flags;
1392 TnyFolder *msg_folder;
1393 gboolean is_html = FALSE;
1394 gboolean field_view_set;
1396 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1397 g_return_if_fail (TNY_IS_MSG (msg));
1399 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1400 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1402 header = tny_msg_get_header (msg);
1403 to = tny_header_dup_to (header);
1404 cc = tny_header_dup_cc (header);
1405 bcc = tny_header_dup_bcc (header);
1406 subject = tny_header_dup_subject (header);
1408 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1409 priority_flags = tny_header_get_priority (header);
1412 gchar *quoted_names = modest_text_utils_quote_names (to);
1413 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), quoted_names);
1414 g_free (quoted_names);
1417 field_view_set = TRUE;
1419 gchar *quoted_names = modest_text_utils_quote_names (cc);
1420 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), quoted_names);
1421 g_free (quoted_names);
1422 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1423 gtk_widget_show (priv->cc_caption);
1424 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1425 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1426 gtk_widget_hide (priv->cc_caption);
1427 field_view_set = FALSE;
1429 modest_togglable_set_active (priv->cc_button, field_view_set);
1431 field_view_set = TRUE;
1433 gchar *quoted_names = modest_text_utils_quote_names (bcc);
1434 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), quoted_names);
1435 g_free (quoted_names);
1436 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1437 gtk_widget_show (priv->bcc_caption);
1438 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1439 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1440 gtk_widget_hide (priv->bcc_caption);
1441 field_view_set = FALSE;
1443 modest_togglable_set_active (priv->bcc_button, field_view_set);
1447 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1448 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1451 update_window_title (self);
1453 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1454 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1456 if ((body == NULL)||(body[0] == '\0')) {
1458 body = modest_text_utils_convert_to_html ("");
1461 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1462 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1465 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1468 /* Add attachments to the view */
1469 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1470 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1471 if (tny_list_get_length (priv->attachments) == 0) {
1472 gtk_widget_hide (priv->attachments_caption);
1474 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1475 gtk_widget_show_all (priv->attachments_caption);
1477 get_related_images (self, msg);
1478 update_next_cid (self, priv->attachments);
1479 update_next_cid (self, priv->images);
1480 replace_with_images (self, priv->images);
1482 if (preserve_is_rich && !is_html) {
1483 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1484 /* Get the default format required from configuration */
1485 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1486 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1489 /* Set the default focus depending on having already a To: field or not */
1490 if ((!to)||(*to == '\0')) {
1491 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1493 gtk_widget_grab_focus (priv->msg_body);
1496 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1498 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1499 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1501 modest_msg_edit_window_set_modified (self, FALSE);
1503 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1504 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1505 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1506 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1508 if (priv->msg_uid) {
1509 g_free (priv->msg_uid);
1510 priv->msg_uid = NULL;
1513 /* we should set a reference to the incoming message if it is a draft */
1514 msg_folder = tny_msg_get_folder (msg);
1516 if (modest_tny_folder_is_local_folder (msg_folder)) {
1517 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1518 if (type == TNY_FOLDER_TYPE_INVALID)
1519 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1521 if (type == TNY_FOLDER_TYPE_DRAFTS)
1522 priv->draft_msg = g_object_ref(msg);
1523 if (type == TNY_FOLDER_TYPE_OUTBOX)
1524 priv->outbox_msg = g_object_ref(msg);
1525 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1527 g_object_unref (msg_folder);
1536 #ifndef MODEST_TOOLKIT_HILDON2
1538 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1541 GList *item_children, *node;
1542 GtkWidget *bin_child;
1544 bin_child = gtk_bin_get_child (GTK_BIN(item));
1546 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1548 for (node = item_children; node != NULL; node = g_list_next (node)) {
1549 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1550 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1553 g_list_free (item_children);
1557 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1560 GList *item_children, *node;
1562 box = gtk_bin_get_child (GTK_BIN (item));
1563 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1564 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1566 for (node = item_children; node != NULL; node = g_list_next (node)) {
1567 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1568 if (GTK_IS_TOGGLE_BUTTON (node->data))
1569 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1570 else if (GTK_IS_BUTTON (node->data))
1571 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1573 g_list_free (item_children);
1578 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1580 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1581 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1582 GtkWidget *placeholder;
1583 GtkWidget *tool_item;
1588 GtkWidget *sizes_menu;
1592 #ifndef MODEST_TOOLKIT_HILDON2
1593 GSList *radio_group, *node;
1594 GtkWidget *fonts_menu;
1598 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1599 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1600 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar),
1601 #ifdef MODEST_TOOLKIT_HILDON2
1602 HILDON_ICON_SIZE_FINGER
1604 GTK_ICON_SIZE_LARGE_TOOLBAR
1607 modest_window_add_toolbar (MODEST_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1609 /* Font color placeholder */
1610 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1611 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1614 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1615 #ifdef MODEST_TOOLKIT_HILDON2
1616 priv->font_color_button = modest_color_button_new ();
1618 priv->font_color_button = gtk_color_button_new ();
1620 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1621 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1622 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1623 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1624 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1625 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1626 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1627 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1629 G_CALLBACK (modest_msg_edit_window_color_button_change),
1632 /* Font size and face placeholder */
1633 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1634 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1636 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, ""));
1637 priv->size_tool_button_label = gtk_label_new (NULL);
1638 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1639 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1640 size_text, "</span>", NULL);
1641 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1642 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1644 #ifdef MODEST_TOOLKIT_HILDON2
1645 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1647 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1648 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1649 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1650 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1651 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1652 gtk_widget_set_sensitive (arrow, FALSE);
1653 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1654 sizes_menu = gtk_menu_new ();
1655 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1656 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1659 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1660 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1662 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1666 if (wp_font_size[size_index] == 12)
1667 priv->current_size_index = size_index;
1671 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1672 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1673 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1674 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1675 priv->font_size_toolitem = tool_item;
1677 #ifdef MODEST_TOOLKIT_HILDON2
1679 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, ""));
1680 priv->font_tool_button_label = gtk_label_new (NULL);
1681 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1682 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1683 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1685 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1686 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1687 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1688 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1689 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1690 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1691 gtk_widget_set_sensitive (arrow, FALSE);
1692 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1694 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1695 priv->font_tool_button_label = gtk_label_new (NULL);
1696 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1697 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1699 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1700 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1701 gtk_widget_show (priv->font_tool_button_label);
1702 gtk_widget_show (GTK_WIDGET (tool_item));
1703 fonts_menu = gtk_menu_new ();
1706 #ifdef MODEST_TOOLKIT_HILDON2
1707 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1708 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1711 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1713 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1714 0, wp_get_font_name (font_index),
1717 if (font_index == DEFAULT_FONT)
1718 priv->current_face_index = font_index;
1720 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1721 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1722 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1723 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1724 priv->font_face_toolitem = tool_item;
1726 priv->font_items_group = NULL;
1728 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1729 GtkWidget *font_menu_item;
1730 GtkWidget *child_label;
1732 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1733 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1734 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1735 wp_get_font_name (font_index), "</span>", NULL);
1736 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1739 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1740 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1741 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1742 gtk_widget_show (font_menu_item);
1744 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1747 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1748 GtkWidget *item = (GtkWidget *) node->data;
1749 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1752 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1753 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1754 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1755 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1756 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1757 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1758 priv->font_face_toolitem = tool_item;
1761 /* Set expand and homogeneous for remaining items */
1762 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1763 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1764 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1765 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1766 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1767 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1768 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsInsertImage");
1769 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1770 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1772 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1773 will not show the tool items added to the placeholders) */
1774 gtk_widget_show_all (parent_priv->toolbar);
1776 /* Set the no show all *after* showing all items. We do not
1777 want the toolbar to be shown with a show all because it
1778 could go against the gconf setting regarding showing or not
1779 the toolbar of the editor window */
1780 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1786 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1789 ModestWindowPrivate *parent_priv;
1790 ModestMsgEditWindowPrivate *priv;
1791 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1792 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1793 ModestWindowMgr *mgr = NULL;
1795 g_return_val_if_fail (msg, NULL);
1796 g_return_val_if_fail (account_name, NULL);
1798 mgr = modest_runtime_get_window_mgr ();
1800 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1802 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1803 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1805 /* Menubar. Update the state of some toggles */
1806 priv->from_field_protos = get_transports ();
1807 priv->original_mailbox = NULL;
1808 modest_selector_set_pair_list (priv->from_field, priv->from_field_protos);
1809 modest_selector_set_active_id (priv->from_field, (gpointer) account_name);
1810 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
1811 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1812 modest_selector_set_active_id (priv->from_field, (gpointer) mailbox);
1813 priv->original_mailbox = g_strdup (mailbox);
1814 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1815 /* We set the first mailbox as the active mailbox */
1816 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1817 if (priv->original_mailbox != NULL)
1818 modest_selector_set_active_id (priv->from_field,
1819 (gpointer) priv->original_mailbox);
1821 modest_selector_set_active_id (priv->from_field,
1822 (gpointer) account_name);
1824 modest_selector_set_active_id (priv->from_field, (gpointer) account_name);
1826 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
1827 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1828 if (!GTK_IS_COMBO_BOX (priv->from_field)) {
1829 #ifdef HILDON_TOOLKIT_HILDON2
1830 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1832 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1833 hildon_touch_selector_get_current_text
1834 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1837 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1838 modest_window_add_toolbar (MODEST_WINDOW (obj), GTK_TOOLBAR (priv->isearch_toolbar));
1841 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1843 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1845 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1846 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1848 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1850 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1851 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1852 /* Add common dimming rules */
1853 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1854 modest_msg_edit_window_toolbar_dimming_entries,
1855 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1856 MODEST_WINDOW (obj));
1857 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1858 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1859 MODEST_WINDOW (obj));
1860 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1861 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1862 MODEST_WINDOW (obj));
1863 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1864 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1865 MODEST_WINDOW (obj));
1866 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1867 G_CALLBACK (modest_ui_dimming_rules_on_send),
1868 MODEST_WINDOW (obj));
1869 /* Insert dimming rules group for this window */
1870 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1871 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1873 /* Setup app menu */
1874 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1876 /* Checks the dimming rules */
1877 g_object_unref (toolbar_rules_group);
1878 g_object_unref (clipboard_rules_group);
1879 gtk_widget_hide (priv->priority_icon);
1880 gtk_widget_queue_resize (priv->subject_box);
1881 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1883 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1885 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1886 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1887 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1888 priv->update_caption_visibility = TRUE;
1890 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1892 /* Track account-removed signal, this window should be closed
1893 in the case we're creating a mail associated to the account
1895 priv->account_removed_handler_id =
1896 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1898 G_CALLBACK(on_account_removed),
1901 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1903 return (ModestWindow*) obj;
1907 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1909 GString **string_buffer = (GString **) user_data;
1911 *string_buffer = g_string_append (*string_buffer, buffer);
1917 * @result: A new string which should be freed with g_free().
1920 get_formatted_data (ModestMsgEditWindow *edit_window)
1922 ModestMsgEditWindowPrivate *priv;
1923 GString *string_buffer = g_string_new ("");
1925 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1927 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1929 modest_text_utils_hyperlinkify (string_buffer);
1931 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1933 return g_string_free (string_buffer, FALSE);
1938 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1941 const gchar *account_name;
1942 ModestMsgEditWindowPrivate *priv;
1943 TnyIterator *att_iter;
1944 const gchar *picker_active_id;
1946 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1948 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1950 picker_active_id = modest_selector_get_active_id (priv->from_field);
1951 g_return_val_if_fail (picker_active_id, NULL);
1952 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1954 /* don't free these (except from) */
1955 data = g_slice_new0 (MsgData);
1956 data->from = g_strdup ((gchar *) modest_selector_get_active_display_name (priv->from_field));
1957 data->account_name = g_strdup (account_name);
1958 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1959 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1960 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1961 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1962 data->references = g_strdup (priv->references);
1963 data->in_reply_to = g_strdup (priv->in_reply_to);
1964 if (priv->draft_msg) {
1965 data->draft_msg = g_object_ref (priv->draft_msg);
1966 } else if (priv->outbox_msg) {
1967 data->draft_msg = g_object_ref (priv->outbox_msg);
1969 data->draft_msg = NULL;
1972 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1974 gtk_text_buffer_get_bounds (buf, &b, &e);
1975 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1977 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1978 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1980 data->html_body = NULL;
1982 /* deep-copy the data */
1983 att_iter = tny_list_create_iterator (priv->attachments);
1984 data->attachments = NULL;
1985 while (!tny_iterator_is_done (att_iter)) {
1986 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1987 if (!(TNY_IS_MIME_PART(part))) {
1988 g_warning ("strange data in attachment list");
1989 g_object_unref (part);
1990 tny_iterator_next (att_iter);
1993 data->attachments = g_list_append (data->attachments,
1995 tny_iterator_next (att_iter);
1997 g_object_unref (att_iter);
1999 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
2000 att_iter = tny_list_create_iterator (priv->images);
2001 data->images = NULL;
2002 while (!tny_iterator_is_done (att_iter)) {
2003 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
2005 if (!(TNY_IS_MIME_PART(part))) {
2006 g_warning ("strange data in attachment list");
2007 g_object_unref (part);
2008 tny_iterator_next (att_iter);
2011 cid = tny_mime_part_get_content_id (part);
2013 gchar *image_tag_id;
2014 GtkTextTag *image_tag;
2016 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
2017 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
2018 g_free (image_tag_id);
2020 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
2022 ((gtk_text_iter_has_tag (&iter, image_tag))||
2023 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
2024 data->images = g_list_append (data->images,
2025 g_object_ref (part));
2027 g_object_unref (part);
2028 tny_iterator_next (att_iter);
2030 g_object_unref (att_iter);
2032 data->priority_flags = priv->priority_flags;
2039 unref_gobject (GObject *obj, gpointer data)
2041 if (!G_IS_OBJECT(obj))
2043 g_object_unref (obj);
2047 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
2050 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
2058 g_free (data->from);
2059 g_free (data->subject);
2060 g_free (data->plain_body);
2061 g_free (data->html_body);
2062 g_free (data->account_name);
2063 g_free (data->references);
2064 g_free (data->in_reply_to);
2066 if (data->draft_msg != NULL) {
2067 g_object_unref (data->draft_msg);
2068 data->draft_msg = NULL;
2071 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
2072 g_list_free (data->attachments);
2073 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
2074 g_list_free (data->images);
2076 g_slice_free (MsgData, data);
2080 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
2082 guint64 *parts_size)
2084 ModestMsgEditWindowPrivate *priv;
2086 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2088 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
2090 /* TODO: add images */
2091 *parts_size += priv->images_size;
2092 *parts_count += priv->images_count;
2097 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
2100 ModestMsgEditWindowPrivate *priv = NULL;
2101 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
2103 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2105 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2107 return MODEST_MSG_EDIT_FORMAT_HTML;
2109 return MODEST_MSG_EDIT_FORMAT_TEXT;
2113 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
2114 ModestMsgEditFormat format)
2116 ModestMsgEditWindowPrivate *priv;
2117 ModestWindowPrivate *parent_priv;
2119 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2120 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2121 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
2124 case MODEST_MSG_EDIT_FORMAT_HTML:
2125 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2126 update_signature (self, priv->last_from_account, priv->last_from_account);
2127 if (parent_priv->toolbar)
2128 on_show_toolbar_button_toggled (priv->show_toolbar_button,
2129 MODEST_MSG_EDIT_WINDOW (self));
2131 case MODEST_MSG_EDIT_FORMAT_TEXT:
2132 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2133 if (parent_priv->toolbar)
2134 on_show_toolbar_button_toggled (priv->show_toolbar_button,
2135 MODEST_MSG_EDIT_WINDOW (self));
2138 g_return_if_reached ();
2142 ModestMsgEditFormatState *
2143 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
2145 ModestMsgEditFormatState *format_state = NULL;
2146 ModestMsgEditWindowPrivate *priv;
2147 WPTextBufferFormat *buffer_format;
2149 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
2151 buffer_format = g_new0 (WPTextBufferFormat, 1);
2152 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2154 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
2156 format_state = g_new0 (ModestMsgEditFormatState, 1);
2157 format_state->bold = buffer_format->bold&0x1;
2158 format_state->italics = buffer_format->italic&0x1;
2159 format_state->bullet = buffer_format->bullet&0x1;
2160 format_state->color = buffer_format->color;
2161 format_state->font_size = buffer_format->font_size;
2162 format_state->font_family = wp_get_font_name (buffer_format->font);
2163 format_state->justification = buffer_format->justification;
2164 g_free (buffer_format);
2166 return format_state;
2171 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
2172 const ModestMsgEditFormatState *format_state)
2174 ModestMsgEditWindowPrivate *priv;
2175 WPTextBufferFormat *buffer_format;
2176 WPTextBufferFormat *current_format;
2178 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2179 g_return_if_fail (format_state != NULL);
2181 buffer_format = g_new0 (WPTextBufferFormat, 1);
2182 current_format = g_new0 (WPTextBufferFormat, 1);
2184 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2185 gtk_widget_grab_focus (priv->msg_body);
2186 buffer_format->bold = (format_state->bold != FALSE);
2187 buffer_format->italic = (format_state->italics != FALSE);
2188 buffer_format->color = format_state->color;
2189 buffer_format->font_size = format_state->font_size;
2190 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
2191 buffer_format->justification = format_state->justification;
2192 buffer_format->bullet = format_state->bullet;
2194 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2196 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2197 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2198 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2199 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2200 buffer_format->cs.font = (buffer_format->font != current_format->font);
2201 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2202 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2204 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2205 if (buffer_format->cs.bold) {
2206 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2207 GINT_TO_POINTER (buffer_format->bold&0x1));
2209 if (buffer_format->cs.italic) {
2210 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2211 GINT_TO_POINTER (buffer_format->italic&0x1));
2213 if (buffer_format->cs.color) {
2214 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2215 GINT_TO_POINTER (&(buffer_format->color)));
2217 if (buffer_format->cs.font_size) {
2218 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2219 GINT_TO_POINTER (buffer_format->font_size));
2221 if (buffer_format->cs.justification) {
2222 switch (buffer_format->justification) {
2223 case GTK_JUSTIFY_LEFT:
2224 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2225 GINT_TO_POINTER(TRUE));
2227 case GTK_JUSTIFY_CENTER:
2228 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2229 GINT_TO_POINTER(TRUE));
2231 case GTK_JUSTIFY_RIGHT:
2232 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2233 GINT_TO_POINTER(TRUE));
2240 if (buffer_format->cs.font) {
2241 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2242 GINT_TO_POINTER (buffer_format->font));
2244 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2245 if (buffer_format->cs.bullet) {
2246 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2247 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2249 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2251 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2253 g_free (buffer_format);
2254 g_free (current_format);
2256 /* Check dimming rules */
2257 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2258 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2262 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2264 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2266 ModestWindowPrivate *parent_priv;
2267 ModestMsgEditWindowPrivate *priv;
2269 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2270 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2272 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2273 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2274 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2275 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2277 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2278 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2279 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2282 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2284 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2285 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2287 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2288 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2290 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2291 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2294 switch (buffer_format->justification)
2296 case GTK_JUSTIFY_LEFT:
2297 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2299 case GTK_JUSTIFY_CENTER:
2300 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2302 case GTK_JUSTIFY_RIGHT:
2303 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2310 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2312 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2313 G_CALLBACK (modest_msg_edit_window_color_button_change),
2315 #ifdef MODEST_TOOLKIT_HILDON2
2316 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2318 gtk_color_button_set_color (GTK_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2320 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2321 G_CALLBACK (modest_msg_edit_window_color_button_change),
2324 if (priv->current_size_index != buffer_format->font_size) {
2328 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2329 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2333 priv->current_size_index = buffer_format->font_size;
2335 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2336 markup = g_strconcat ("<span font_family='Sans'>",
2337 size_text, "</span>", NULL);
2339 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2343 gtk_tree_path_free (path);
2346 #ifdef MODEST_TOOLKIT_HILDON2
2347 if (priv->current_face_index != buffer_format->font) {
2351 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2352 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2356 priv->current_face_index = buffer_format->font;
2357 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2358 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2359 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2366 GtkWidget *new_font_menuitem;
2367 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
2368 buffer_format->font))->data);
2369 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
2373 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2374 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2375 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2377 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2378 G_CALLBACK (modest_msg_edit_window_font_change),
2380 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2381 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2382 G_CALLBACK (modest_msg_edit_window_font_change),
2387 g_free (buffer_format);
2393 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2395 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2396 ModestMsgEditWindowPrivate *priv;
2397 GtkWidget *dialog = NULL;
2399 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2400 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2402 #ifdef MODEST_TOOLKIT_HILDON2
2403 dialog = hildon_color_chooser_new ();
2404 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2405 g_free (buffer_format);
2407 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2409 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2410 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2413 gtk_widget_destroy (dialog);
2415 dialog = gtk_color_selection_dialog_new (NULL);
2416 GtkWidget *selection;
2418 g_object_get (G_OBJECT (dialog), "color_selection", &selection, NULL);
2419 gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (selection), &(buffer_format->color));
2420 gtk_color_selection_set_previous_color (GTK_COLOR_SELECTION (selection), &(buffer_format->color));
2421 g_free (buffer_format);
2423 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2425 gtk_color_selection_get_current_color (GTK_COLOR_SELECTION(selection), &col);
2426 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2429 gtk_widget_destroy (dialog);
2436 create_stream_for_uri (const gchar* uri)
2441 TnyStream *result = NULL;
2443 GnomeVFSHandle *handle = NULL;
2444 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2445 if (test == GNOME_VFS_OK) {
2446 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2447 /* Streams over OBEX (Bluetooth) are not seekable but
2448 * we expect them to be (we might need to read them
2449 * several times). So if this is a Bluetooth URI just
2450 * read the whole file into memory (this is not a fast
2451 * protocol so we can assume that these files are not
2452 * going to be very big) */
2453 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2454 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2455 TnyStream *memstream = tny_camel_mem_stream_new ();
2456 tny_stream_write_to_stream (vfssstream, memstream);
2457 g_object_unref (vfssstream);
2460 result = vfssstream;
2468 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2471 ModestMsgEditWindowPrivate *priv;
2472 GtkWidget *dialog = NULL;
2474 GSList *uris = NULL;
2475 GSList *uri_node = NULL;
2477 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2479 dialog = modest_toolkit_factory_create_file_chooser_dialog (modest_runtime_get_toolkit_factory (),
2480 _("mcen_ia_select_inline_image_title"),
2481 (GtkWindow *) window,
2482 GTK_FILE_CHOOSER_ACTION_OPEN);
2483 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2485 #ifdef MODEST_TOOLKIT_HILDON2
2486 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2489 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2490 GTK_WINDOW (dialog), GTK_WINDOW (window));
2492 response = gtk_dialog_run (GTK_DIALOG (dialog));
2494 case GTK_RESPONSE_OK:
2496 gchar *current_folder;
2497 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2498 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2499 if (current_folder && current_folder != '\0') {
2501 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2502 current_folder, &err);
2504 g_debug ("Error storing latest used folder: %s", err->message);
2508 g_free (current_folder);
2514 gtk_widget_destroy (dialog);
2516 g_object_ref (window);
2517 /* The operation could take some time so allow the dialog to be closed */
2518 while (gtk_events_pending ())
2519 gtk_main_iteration ();
2521 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2523 GnomeVFSHandle *handle = NULL;
2524 GnomeVFSResult result;
2525 GtkTextIter position;
2526 GtkTextMark *insert_mark;
2528 uri = (const gchar *) uri_node->data;
2529 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2530 if (result == GNOME_VFS_OK) {
2532 GnomeVFSFileInfo *info;
2533 gchar *filename, *basename, *escaped_filename;
2534 TnyMimePart *mime_part;
2536 const gchar *mime_type = NULL;
2537 GnomeVFSURI *vfs_uri;
2538 guint64 stream_size;
2540 gnome_vfs_close (handle);
2541 vfs_uri = gnome_vfs_uri_new (uri);
2543 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2544 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2545 g_free (escaped_filename);
2546 gnome_vfs_uri_unref (vfs_uri);
2547 info = gnome_vfs_file_info_new ();
2549 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2550 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2552 mime_type = gnome_vfs_file_info_get_mime_type (info);
2554 mime_part = tny_platform_factory_new_mime_part
2555 (modest_runtime_get_platform_factory ());
2557 TnyStream *stream = create_stream_for_uri (uri);
2559 if (stream == NULL) {
2561 modest_platform_information_banner (NULL, NULL,
2562 _FM_OPENING_NOT_ALLOWED);
2564 g_object_unref (mime_part);
2565 gnome_vfs_file_info_unref (info);
2569 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2571 content_id = g_strdup_printf ("%d", priv->next_cid);
2572 tny_mime_part_set_content_id (mime_part, content_id);
2573 g_free (content_id);
2576 basename = g_path_get_basename (filename);
2577 tny_mime_part_set_filename (mime_part, basename);
2580 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2582 if (pixbuf != NULL) {
2583 priv->images_size += stream_size;
2584 priv->images_count ++;
2585 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2586 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2587 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2588 tny_mime_part_get_content_id (mime_part), pixbuf);
2589 g_object_unref (pixbuf);
2591 tny_list_prepend (priv->images, (GObject *) mime_part);
2592 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2594 modest_platform_information_banner (NULL, NULL,
2595 _("mail_ib_file_operation_failed"));
2599 g_object_unref (mime_part);
2600 gnome_vfs_file_info_unref (info);
2604 g_object_unref (window);
2608 on_attach_file_response (GtkDialog *dialog,
2612 GSList *uris = NULL;
2614 GnomeVFSFileSize total_size, allowed_size;
2615 ModestMsgEditWindow *window;
2616 ModestMsgEditWindowPrivate *priv;
2621 case GTK_RESPONSE_OK:
2623 gchar *current_folder;
2625 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2626 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2627 if (current_folder && current_folder != '\0') {
2629 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2630 current_folder, &err);
2632 g_debug ("Error storing latest used folder: %s", err->message);
2636 g_free (current_folder);
2643 window = MODEST_MSG_EDIT_WINDOW (user_data);
2644 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2646 /* allowed size is the maximum size - what's already there */
2647 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2648 &att_num, &att_size);
2649 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2652 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2654 const gchar *uri = (const gchar *) uri_node->data;
2657 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2659 if (total_size > allowed_size) {
2660 g_debug ("%s: total size: %u",
2661 __FUNCTION__, (unsigned int)total_size);
2664 allowed_size -= total_size;
2666 g_slist_foreach (uris, (GFunc) g_free, NULL);
2667 g_slist_free (uris);
2669 gtk_widget_destroy (GTK_WIDGET (dialog));
2673 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2675 GtkWidget *dialog = NULL;
2676 ModestMsgEditWindowPrivate *priv;
2679 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2681 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2683 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2686 dialog = modest_toolkit_factory_create_file_chooser_dialog (modest_runtime_get_toolkit_factory (),
2687 _("mcen_ia_select_attachment_title"),
2688 (GtkWindow *) window,
2689 GTK_FILE_CHOOSER_ACTION_OPEN);
2690 conf_folder = modest_conf_get_string (modest_runtime_get_conf (),
2691 MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2692 if (conf_folder && conf_folder[0] != '\0') {
2693 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2696 /* Set the default folder to documents folder */
2697 docs_folder = (gchar *) g_strdup(g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
2698 #ifdef MODEST_TOOLKIT_HILDON2
2701 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2702 ".documents", NULL);
2705 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2706 g_free (docs_folder);
2708 g_free (conf_folder);
2709 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2710 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2711 GTK_WINDOW (dialog), GTK_WINDOW (window));
2713 /* Connect to response & show */
2714 g_signal_connect (dialog, "response",
2715 G_CALLBACK (on_attach_file_response), window);
2716 gtk_widget_show (dialog);
2721 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2723 GnomeVFSFileSize allowed_size)
2726 GnomeVFSHandle *handle = NULL;
2727 ModestMsgEditWindowPrivate *priv;
2728 GnomeVFSResult result;
2729 GnomeVFSFileSize size = 0;
2730 g_return_val_if_fail (window, 0);
2731 g_return_val_if_fail (uri, 0);
2733 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2735 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2736 if (result == GNOME_VFS_OK) {
2737 TnyMimePart *mime_part;
2739 const gchar *mime_type = NULL;
2741 gchar *escaped_filename;
2744 GnomeVFSFileInfo *info;
2745 GnomeVFSURI *vfs_uri;
2747 gnome_vfs_close (handle);
2748 vfs_uri = gnome_vfs_uri_new (uri);
2751 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2752 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2753 g_free (escaped_filename);
2754 gnome_vfs_uri_unref (vfs_uri);
2756 info = gnome_vfs_file_info_new ();
2758 if (gnome_vfs_get_file_info (uri,
2760 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2762 mime_type = gnome_vfs_file_info_get_mime_type (info);
2763 mime_part = tny_platform_factory_new_mime_part
2764 (modest_runtime_get_platform_factory ());
2766 /* try to get the attachment's size; this may fail for weird
2767 * file systems, like obex, upnp... */
2768 if (allowed_size != 0 &&
2769 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2771 if (size > allowed_size) {
2772 modest_platform_information_banner (NULL, NULL,
2773 _("mail_ib_error_attachment_size"));
2778 g_debug ("%s: could not get attachment size", __FUNCTION__);
2780 stream = create_stream_for_uri (uri);
2782 if (stream == NULL) {
2784 modest_platform_information_banner (NULL, NULL, _FM_OPENING_NOT_ALLOWED);
2786 g_object_unref (mime_part);
2788 gnome_vfs_file_info_unref (info);
2792 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2793 g_object_unref (stream);
2795 content_id = g_strdup_printf ("%d", priv->next_cid);
2796 tny_mime_part_set_content_id (mime_part, content_id);
2797 g_free (content_id);
2800 basename = g_path_get_basename (filename);
2801 tny_mime_part_set_filename (mime_part, basename);
2804 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2805 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2807 info->size == 0, info->size);
2808 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2809 gtk_widget_show_all (priv->attachments_caption);
2810 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2812 g_object_unref (mime_part);
2813 gnome_vfs_file_info_unref (info);
2820 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2823 ModestMsgEditWindowPrivate *priv;
2826 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2827 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2829 if (att_list == NULL) {
2830 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2831 if (!modest_toolkit_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2832 g_object_unref (att_list);
2836 g_object_ref (att_list);
2839 if (tny_list_get_length (att_list) == 0) {
2840 modest_platform_system_banner (NULL, NULL, _("TODO: no attachments selected to remove"));
2842 gboolean dialog_response;
2843 gchar *message = NULL;
2844 gchar *filename = NULL;
2846 if (tny_list_get_length (att_list) == 1) {
2848 iter = tny_list_create_iterator (att_list);
2849 part = (TnyMimePart *) tny_iterator_get_current (iter);
2850 g_object_unref (iter);
2851 if (TNY_IS_MSG (part)) {
2852 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2854 filename = tny_header_dup_subject (header);
2855 g_object_unref (header);
2857 if (filename == NULL) {
2858 filename = g_strdup (_("mail_va_no_subject"));
2861 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2863 g_object_unref (part);
2865 filename = g_strdup ("");
2867 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2868 "emev_nc_delete_attachments",
2869 tny_list_get_length (att_list)), filename);
2872 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2876 if (dialog_response != GTK_RESPONSE_OK) {
2877 g_object_unref (att_list);
2881 for (iter = tny_list_create_iterator (att_list);
2882 !tny_iterator_is_done (iter);
2883 tny_iterator_next (iter)) {
2884 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2885 const gchar *att_id;
2886 tny_list_remove (priv->attachments, (GObject *) mime_part);
2888 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2890 if (tny_list_get_length (priv->attachments) == 0)
2891 gtk_widget_hide (priv->attachments_caption);
2892 att_id = tny_mime_part_get_content_id (mime_part);
2894 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2896 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2897 g_object_unref (mime_part);
2899 g_object_unref (iter);
2902 g_object_unref (att_list);
2904 /* if the last attachment has been removed, focus the Subject: field */
2905 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2906 gtk_widget_grab_focus (priv->subject_field);
2910 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2913 ModestMsgEditWindowPrivate *priv;
2916 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2918 gtk_color_button_get_color (GTK_COLOR_BUTTON(priv->font_color_button), &new_color);
2920 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) &new_color);
2922 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2925 #ifndef MODEST_TOOLKIT_HILDON2
2927 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2930 ModestMsgEditWindowPrivate *priv;
2931 gint new_font_index;
2932 ModestMsgEditWindow *window;
2935 window = MODEST_MSG_EDIT_WINDOW (userdata);
2936 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2937 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2939 if (gtk_check_menu_item_get_active (menu_item)) {
2942 label = gtk_bin_get_child (GTK_BIN (menu_item));
2944 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2946 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2947 GINT_TO_POINTER(new_font_index)))
2948 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2950 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2951 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2952 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2959 font_size_clicked (GtkToolButton *button,
2960 ModestMsgEditWindow *window)
2962 #ifdef MODEST_TOOLKIT_HILDON2
2963 ModestMsgEditWindowPrivate *priv;
2964 GtkWidget *selector, *dialog;
2966 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2968 selector = hildon_touch_selector_new ();
2969 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2970 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2972 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2973 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2974 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2976 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2980 WPTextBufferFormat format;
2982 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2984 memset (&format, 0, sizeof (format));
2985 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2987 format.cs.font_size = TRUE;
2988 format.cs.text_position = TRUE;
2989 format.cs.font = TRUE;
2990 format.font_size = new_index;
2991 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2993 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2994 GINT_TO_POINTER (new_index)))
2995 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2997 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2998 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2999 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
3000 size_text, "</span>", NULL);
3002 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
3006 gtk_widget_destroy (dialog);
3008 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
3012 #ifdef MODEST_TOOLKIT_HILDON2
3014 font_face_clicked (GtkToolButton *button,
3015 ModestMsgEditWindow *window)
3017 ModestMsgEditWindowPrivate *priv;
3018 GtkWidget *selector, *dialog;
3019 GtkCellRenderer *renderer;
3021 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3023 selector = hildon_touch_selector_new ();
3024 renderer = gtk_cell_renderer_text_new ();
3025 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
3026 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
3027 renderer, "family", 0, "text", 0, NULL);
3028 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
3030 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
3031 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
3032 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
3034 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
3035 gint new_font_index;
3039 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
3040 path = gtk_tree_path_new_from_indices (new_font_index, -1);
3041 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
3045 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
3047 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
3048 GINT_TO_POINTER(new_font_index)))
3049 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
3051 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
3052 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
3054 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
3058 gtk_tree_path_free (path);
3061 gtk_widget_destroy (dialog);
3063 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
3068 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
3071 ModestMsgEditWindowPrivate *priv = NULL;
3072 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3074 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3075 if (!priv->update_caption_visibility)
3078 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
3080 gtk_widget_show (priv->cc_caption);
3082 gtk_widget_hide (priv->cc_caption);
3084 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
3088 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
3091 ModestMsgEditWindowPrivate *priv = NULL;
3092 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3094 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3095 if (!priv->update_caption_visibility)
3098 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
3100 gtk_widget_show (priv->bcc_caption);
3102 gtk_widget_hide (priv->bcc_caption);
3104 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
3108 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
3109 ModestRecptEditor *editor)
3111 ModestMsgEditWindowPrivate *priv;
3113 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3114 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
3116 /* we check for low-mem; in that case, show a warning, and don't allow
3117 * for the addressbook
3119 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3122 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3124 if (editor == NULL) {
3125 GtkWidget *view_focus, *parent;
3126 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
3128 /* This code should be kept in sync with ModestRecptEditor. The
3129 textview inside the recpt editor is the one that really gets the
3130 focus. As it's inside a scrolled window, and this one inside the
3131 hbox recpt editor inherits from, we'll need to go up in the
3132 hierarchy to know if the text view is part of the recpt editor
3133 or if it's a different text entry */
3134 parent = gtk_widget_get_parent (view_focus);
3135 if (parent && MODEST_IS_RECPT_EDITOR (parent))
3136 editor = MODEST_RECPT_EDITOR (parent);
3139 editor = MODEST_RECPT_EDITOR (priv->to_field);
3142 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
3146 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
3148 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3150 modest_msg_edit_window_open_addressbook (window, NULL);
3154 modest_msg_edit_window_show_toolbar (ModestWindow *self,
3155 gboolean show_toolbar)
3157 ModestWindowPrivate *parent_priv;
3158 ModestMsgEditWindowPrivate *priv;
3160 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
3161 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3162 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
3164 /* We can not just use the code of
3165 modest_msg_edit_window_setup_toolbar because it has a
3166 mixture of both initialization and creation code. */
3168 gint current_format;
3169 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3170 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3171 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3172 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3174 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
3177 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3179 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, show_toolbar, NULL);
3180 if (modest_togglable_get_active (priv->show_toolbar_button) != show_toolbar) {
3181 modest_togglable_set_active (priv->show_toolbar_button, show_toolbar);
3186 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
3187 TnyHeaderFlags priority_flags)
3189 ModestMsgEditWindowPrivate *priv;
3190 ModestWindowPrivate *parent_priv;
3192 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3194 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3195 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3197 if (priv->priority_flags != priority_flags) {
3198 GtkAction *priority_action = NULL;
3200 priv->priority_flags = priority_flags;
3202 switch (priority_flags) {
3203 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3204 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3205 MODEST_HEADER_ICON_HIGH,
3206 #ifdef MODEST_TOOLKIT_HILDON2
3207 HILDON_ICON_SIZE_SMALL
3209 GTK_ICON_SIZE_BUTTON
3212 gtk_widget_show (priv->priority_icon);
3213 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3214 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
3216 case TNY_HEADER_FLAG_LOW_PRIORITY:
3217 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3218 MODEST_HEADER_ICON_LOW,
3219 #ifdef MODEST_TOOLKIT_HILDON2
3220 HILDON_ICON_SIZE_SMALL
3222 GTK_ICON_SIZE_BUTTON
3225 gtk_widget_show (priv->priority_icon);
3226 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3227 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3230 gtk_widget_hide (priv->priority_icon);
3231 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3232 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3235 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3236 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3238 gtk_widget_queue_resize (priv->subject_box);
3242 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3245 ModestMsgEditWindowPrivate *priv;
3246 ModestWindowPrivate *parent_priv;
3247 gint current_format;
3249 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3251 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3252 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3254 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3255 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3257 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3259 if (current_format != file_format) {
3260 switch (file_format) {
3261 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3262 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3263 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3264 update_signature (window, priv->last_from_account, priv->last_from_account);
3265 if (parent_priv->toolbar)
3266 on_show_toolbar_button_toggled (priv->show_toolbar_button,
3267 MODEST_MSG_EDIT_WINDOW (window));
3269 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3272 response = modest_platform_run_confirmation_dialog (NULL, _("emev_nc_formatting_lost"));
3273 if (response == GTK_RESPONSE_OK) {
3274 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3275 if (parent_priv->toolbar)
3276 on_show_toolbar_button_toggled (priv->show_toolbar_button,
3277 MODEST_MSG_EDIT_WINDOW (window));
3279 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3280 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3285 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3286 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3287 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3292 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3294 #ifdef MODEST_TOOLKIT_HILDON2
3296 ModestMsgEditWindowPrivate *priv;
3297 WPTextBufferFormat oldfmt, fmt;
3298 gint old_position = 0;
3302 GdkColor *color = NULL;
3303 gboolean bold, bold_set, italic, italic_set;
3304 gboolean underline, underline_set;
3305 gboolean strikethrough, strikethrough_set;
3306 gboolean position_set;
3307 gboolean font_size_set, font_set, color_set;
3310 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3311 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3313 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3314 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3315 GTK_WINDOW(dialog), GTK_WINDOW (window));
3317 /* First we get the currently selected font information */
3318 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3320 switch (oldfmt.text_position) {
3321 case TEXT_POSITION_NORMAL:
3324 case TEXT_POSITION_SUPERSCRIPT:
3332 g_object_set (G_OBJECT (dialog),
3333 "bold", oldfmt.bold != FALSE,
3334 "bold-set", !oldfmt.cs.bold,
3335 "underline", oldfmt.underline != FALSE,
3336 "underline-set", !oldfmt.cs.underline,
3337 "italic", oldfmt.italic != FALSE,
3338 "italic-set", !oldfmt.cs.italic,
3339 "strikethrough", oldfmt.strikethrough != FALSE,
3340 "strikethrough-set", !oldfmt.cs.strikethrough,
3341 "color", &oldfmt.color,
3342 "color-set", !oldfmt.cs.color,
3343 "size", wp_font_size[oldfmt.font_size],
3344 "size-set", !oldfmt.cs.font_size,
3345 "position", old_position,
3346 "position-set", !oldfmt.cs.text_position,
3347 "family", wp_get_font_name (oldfmt.font),
3348 "family-set", !oldfmt.cs.font,
3351 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3352 GTK_WINDOW (dialog), GTK_WINDOW (window));
3353 gtk_widget_show_all (dialog);
3354 priv->font_dialog = dialog;
3355 response = gtk_dialog_run (GTK_DIALOG (dialog));
3356 priv->font_dialog = NULL;
3357 if (response == GTK_RESPONSE_OK) {
3359 g_object_get( dialog,
3361 "bold-set", &bold_set,
3362 "underline", &underline,
3363 "underline-set", &underline_set,
3365 "italic-set", &italic_set,
3366 "strikethrough", &strikethrough,
3367 "strikethrough-set", &strikethrough_set,
3369 "color-set", &color_set,
3371 "size-set", &font_size_set,
3372 "family", &font_name,
3373 "family-set", &font_set,
3374 "position", &position,
3375 "position-set", &position_set,
3380 if (response == GTK_RESPONSE_OK) {
3381 memset(&fmt, 0, sizeof(fmt));
3387 fmt.italic = italic;
3388 fmt.cs.italic = TRUE;
3390 if (underline_set) {
3391 fmt.underline = underline;
3392 fmt.cs.underline = TRUE;
3394 if (strikethrough_set) {
3395 fmt.strikethrough = strikethrough;
3396 fmt.cs.strikethrough = TRUE;
3401 ? TEXT_POSITION_NORMAL
3402 : ( ( position == 1 )
3403 ? TEXT_POSITION_SUPERSCRIPT
3404 : TEXT_POSITION_SUBSCRIPT );
3405 fmt.cs.text_position = TRUE;
3406 fmt.font_size = oldfmt.font_size;
3410 fmt.cs.color = TRUE;
3413 fmt.font = wp_get_font_index(font_name,
3418 if (font_size_set) {
3419 fmt.cs.font_size = TRUE;
3420 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3422 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3423 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3425 gtk_widget_destroy (dialog);
3427 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3432 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3434 ModestMsgEditWindowPrivate *priv;
3435 ModestWindowPrivate *parent_priv;
3436 gboolean was_rich_text, is_rich_text;
3438 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3439 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3440 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3442 was_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3444 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3446 is_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3448 if (parent_priv->toolbar && was_rich_text != is_rich_text) {
3449 on_show_toolbar_button_toggled (priv->show_toolbar_button,
3450 MODEST_MSG_EDIT_WINDOW (window));
3453 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3454 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3458 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3460 ModestMsgEditWindowPrivate *priv;
3462 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3463 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3465 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3467 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3468 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3473 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3475 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3477 priv->can_undo = can_undo;
3481 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3483 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3485 priv->can_redo = can_redo;
3489 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3491 ModestMsgEditWindowPrivate *priv;
3492 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3493 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3495 return priv->can_undo;
3499 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3501 ModestMsgEditWindowPrivate *priv;
3502 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3503 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3505 return priv->can_redo;
3510 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3513 GtkTextIter match_start, match_end;
3515 if (image_id == NULL)
3518 gtk_text_buffer_get_start_iter (buffer, &iter);
3520 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3521 GSList *tags = gtk_text_iter_get_tags (&match_start);
3523 for (node = tags; node != NULL; node = g_slist_next (node)) {
3524 GtkTextTag *tag = (GtkTextTag *) node->data;
3525 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3526 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3527 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3529 offset = gtk_text_iter_get_offset (&match_start);
3530 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3531 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3535 gtk_text_iter_forward_char (&iter);
3540 message_is_empty (ModestMsgEditWindow *window)
3542 ModestMsgEditWindowPrivate *priv = NULL;
3544 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3545 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3547 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3548 * so we can ignore markup.
3550 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3553 count = gtk_text_buffer_get_char_count (buf);
3559 msg_body_focus (GtkWidget *focus,
3560 GdkEventFocus *event,
3564 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3565 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3566 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3571 recpt_field_changed (GtkTextBuffer *buffer,
3572 ModestMsgEditWindow *editor)
3574 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3575 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3579 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3581 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3582 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3586 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3589 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3590 GtkTextBuffer *buffer;
3592 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3593 gtk_text_buffer_set_modified (buffer, modified);
3594 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3595 gtk_text_buffer_set_modified (buffer, modified);
3596 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3597 gtk_text_buffer_set_modified (buffer, modified);
3598 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3602 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3604 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3605 const char *account_name;
3606 GtkTextBuffer *buffer;
3608 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3609 if (gtk_text_buffer_get_modified (buffer))
3611 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3612 if (gtk_text_buffer_get_modified (buffer))
3614 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3615 if (gtk_text_buffer_get_modified (buffer))
3617 if (gtk_text_buffer_get_modified (priv->text_buffer))
3620 account_name = modest_selector_get_active_id (priv->from_field);
3621 if (priv->original_mailbox) {
3622 if (!account_name || strcmp (account_name, priv->original_mailbox))
3624 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3635 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3637 ModestMsgEditWindowPrivate *priv = NULL;
3638 GSList *address_list = NULL;
3639 gboolean no_to, no_cc, no_bcc;
3641 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3642 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3644 /* check if there's no recipient added */
3645 no_to = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)));
3646 no_cc = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field)));
3647 no_bcc = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field)));
3650 if (no_to && no_cc && no_bcc) {
3651 /* no recipient contents, then select contacts */
3652 modest_msg_edit_window_open_addressbook (window, NULL);
3657 g_object_ref (window);
3658 if (!no_to && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field),
3659 (add_to_addressbook) ? &address_list : NULL)) {
3660 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3661 g_object_unref (window);
3664 if (!no_cc && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field),
3665 (add_to_addressbook) ? &address_list : NULL)) {
3666 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3667 g_object_unref (window);
3670 if (!no_bcc && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field),
3671 (add_to_addressbook) ? &address_list : NULL)) {
3672 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3673 g_object_unref (window);
3677 /* Add contacts to address book */
3678 if (add_to_addressbook && address_list)
3679 modest_address_book_add_address_list (address_list);
3681 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3682 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3683 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3684 g_object_unref (window);
3691 modest_msg_edit_window_add_to_contacts (ModestMsgEditWindow *self)
3693 GSList *recipients = NULL;
3694 ModestMsgEditWindowPrivate *priv;
3695 gchar *joined, *after_remove, *to, *cc, *bcc;
3697 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3699 /* First of all check names */
3700 if (!modest_msg_edit_window_check_names (self, FALSE))
3703 if (!modest_msg_edit_window_has_pending_addresses (self))
3706 /* Don't add the from obviously */
3707 to = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->to_field));
3708 cc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->cc_field));
3709 bcc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->bcc_field));
3711 joined = modest_text_utils_join_addresses (NULL, to, cc, bcc);
3716 after_remove = modest_text_utils_remove_duplicate_addresses (joined);
3719 recipients = modest_text_utils_split_addresses_list (after_remove);
3720 g_free (after_remove);
3723 /* Offer the user to add recipients to the address book */
3724 modest_address_book_add_address_list_with_selector (recipients, (GtkWindow *) self);
3725 g_slist_foreach (recipients, (GFunc) g_free, NULL); g_slist_free (recipients);
3730 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3731 ModestMsgEditWindow *window)
3733 modest_msg_edit_window_offer_attach_file (window);
3737 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3739 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3741 return priv->clipboard_text;
3745 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3747 ModestMsgEditWindow *window)
3749 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3750 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3753 /* It could happen that the window was already closed */
3754 if (!GTK_WIDGET_VISIBLE (window))
3757 g_object_ref (window);
3758 text = gtk_clipboard_wait_for_text (selection_clipboard);
3760 if (priv->clipboard_text != NULL) {
3761 g_free (priv->clipboard_text);
3763 priv->clipboard_text = text;
3765 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3767 g_object_unref (window);
3770 static gboolean clipboard_owner_change_idle (gpointer userdata)
3772 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3773 ModestMsgEditWindowPrivate *priv;
3775 gdk_threads_enter ();
3776 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3777 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3779 priv->clipboard_owner_idle = 0;
3780 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3781 gdk_threads_leave ();
3787 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3789 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3790 if (priv->clipboard_owner_idle == 0) {
3791 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3792 clipboard_owner_change_idle,
3793 g_object_ref (window),
3799 subject_field_move_cursor (GtkEntry *entry,
3800 GtkMovementStep step,
3805 /* It could happen that the window was already closed */
3806 if (!GTK_WIDGET_VISIBLE (window))
3809 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3813 update_window_title (ModestMsgEditWindow *window)
3815 ModestMsgEditWindowPrivate *priv = NULL;
3816 const gchar *subject;
3818 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3819 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3820 if (subject == NULL || subject[0] == '\0')
3821 subject = _("mail_va_new_email");
3823 modest_window_set_title (MODEST_WINDOW (window), subject);
3829 body_insert_text (GtkTextBuffer *buffer,
3830 GtkTextIter *location,
3833 ModestMsgEditWindow *window)
3835 GtkTextIter end_iter;
3842 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3844 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3846 offset = gtk_text_iter_get_offset (&end_iter);
3847 line = gtk_text_iter_get_line (&end_iter);
3851 while (text_offset < text + len) {
3852 if (*text_offset == '\n')
3854 if (text_lines + line >= MAX_BODY_LINES) {
3855 len = text_offset - text;
3861 utf8_len = g_utf8_strlen (text, len);
3863 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3864 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3865 if (line <= MAX_BODY_LINES && offset < MAX_BODY_LENGTH)
3870 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3872 /* Prevent endless recursion */
3873 result = g_strndup (text, utf8_end - text);
3874 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3875 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3876 (gpointer) result, (gpointer) (utf8_end - text),
3878 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3882 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3883 if (priv->max_chars_banner == NULL) {
3884 #ifdef MODEST_TOOLKIT_HILDON2
3885 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3886 _CS_MAXIMUM_CHARACTERS_REACHED);
3887 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3894 subject_field_changed (GtkEditable *editable,
3895 ModestMsgEditWindow *window)
3897 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3898 update_window_title (window);
3899 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3900 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3901 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3904 subject_field_insert_text (GtkEditable *editable,
3906 gint new_text_length,
3908 ModestMsgEditWindow *window)
3910 GString *result = g_string_new ("");
3912 gint result_len = 0;
3913 const gchar *entry_text = NULL;
3916 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3917 old_length = g_utf8_strlen (entry_text, -1);
3919 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3920 gunichar c = g_utf8_get_char_validated (current, 8);
3921 /* Invalid unichar, stop */
3927 result = g_string_append_unichar (result, c);
3931 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3932 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3935 /* Prevent endless recursion */
3936 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3937 g_signal_emit_by_name (editable, "insert-text",
3938 (gpointer) result->str, (gpointer) result->len,
3939 (gpointer) position, (gpointer) window);
3940 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3944 if (result_len + old_length > 1000) {
3945 modest_platform_system_banner (GTK_WIDGET (window), NULL,
3946 _CS_MAXIMUM_CHARACTERS_REACHED);
3948 g_string_free (result, TRUE);
3952 modest_msg_edit_window_toggle_isearch_toolbar (ModestMsgEditWindow *window,
3955 ModestMsgEditWindowPrivate *priv = NULL;
3957 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3958 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3960 gtk_widget_set_no_show_all (priv->isearch_toolbar, FALSE);
3963 gtk_widget_show_all (priv->isearch_toolbar);
3964 modest_isearch_toolbar_highlight_entry (MODEST_ISEARCH_TOOLBAR (priv->isearch_toolbar), TRUE);
3966 gtk_widget_hide_all (priv->isearch_toolbar);
3967 gtk_widget_grab_focus (priv->msg_body);
3972 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3974 GtkTextIter *match_start,
3975 GtkTextIter *match_end)
3977 GtkTextIter end_iter;
3978 gchar *str_casefold;
3981 gchar *range_casefold;
3984 gboolean result = FALSE;
3991 gtk_text_iter_forward_to_end (&end_iter);
3993 str_casefold = g_utf8_casefold (str, -1);
3994 str_chars_n = strlen (str);
3996 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3997 range_casefold = g_utf8_casefold (range_text, -1);
3998 range_chars_n = strlen (range_casefold);
4000 if (range_chars_n < str_chars_n) {
4001 g_free (str_casefold);
4002 g_free (range_text);
4003 g_free (range_casefold);
4007 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
4008 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
4009 if (!g_utf8_collate (range_subtext, str_casefold)) {
4010 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
4012 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
4013 match_start, match_end, NULL)) {
4014 g_debug ("Matched string with collate, but not matched in model");
4016 g_free (found_text);
4018 g_free (range_subtext);
4022 g_free (str_casefold);
4023 g_free (range_text);
4024 g_free (range_casefold);
4031 modest_msg_edit_window_isearch_toolbar_search (GtkWidget *widget,
4032 ModestMsgEditWindow *window)
4034 const gchar *current_search = NULL;
4035 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4037 GtkTextIter selection_start, selection_end;
4038 GtkTextIter match_start, match_end;
4039 gboolean continue_search = FALSE;
4041 if (message_is_empty (window)) {
4042 g_free (priv->last_search);
4043 priv->last_search = NULL;
4044 modest_platform_system_banner (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
4048 current_search = modest_isearch_toolbar_get_search (MODEST_ISEARCH_TOOLBAR (widget));
4049 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
4050 g_free (priv->last_search);
4051 priv->last_search = NULL;
4052 /* Information banner about empty search */
4053 modest_platform_system_banner (NULL, NULL, _CS_FIND_REP_ENTER_TEXT);
4057 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
4058 continue_search = TRUE;
4060 g_free (priv->last_search);
4061 priv->last_search = g_strdup (current_search);
4064 if (continue_search) {
4065 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
4066 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
4067 &match_start, &match_end);
4069 modest_platform_system_banner (NULL, NULL, _HL_IB_FIND_COMPLETE);
4071 GtkTextIter buffer_start;
4072 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
4073 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
4074 &match_start, &match_end);
4076 modest_platform_system_banner (NULL, NULL, _HL_IB_FIND_NO_MATCHES);
4079 /* Mark as selected the string found in search */
4081 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
4082 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
4083 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
4085 g_free (priv->last_search);
4086 priv->last_search = NULL;
4091 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
4093 ModestMsgEditWindowPrivate *priv;
4095 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
4100 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
4103 ModestMsgEditWindowPrivate *priv;
4105 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
4110 modest_msg_edit_window_isearch_toolbar_close (GtkWidget *widget,
4111 ModestMsgEditWindow *window)
4113 modest_msg_edit_window_toggle_isearch_toolbar (window, FALSE);
4117 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
4120 ModestMsgEditWindowPrivate *priv;
4121 TnyHeader *header = NULL;
4123 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4124 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
4126 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4128 if (priv->draft_msg != NULL) {
4129 g_object_unref (priv->draft_msg);
4132 if (draft != NULL) {
4133 g_object_ref (draft);
4134 header = tny_msg_get_header (draft);
4135 if (priv->msg_uid) {
4136 g_free (priv->msg_uid);
4137 priv->msg_uid = NULL;
4139 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
4142 priv->draft_msg = draft;
4146 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
4147 GtkTextIter *start, GtkTextIter *end,
4150 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
4151 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
4154 if (tag == NULL) return;
4155 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
4156 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
4157 replace_with_images (window, priv->images);
4162 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
4165 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4167 g_return_if_fail (TNY_IS_MIME_PART (part));
4168 tny_list_prepend (priv->attachments, (GObject *) part);
4169 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
4170 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
4171 gtk_widget_show_all (priv->attachments_caption);
4172 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
4176 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
4178 ModestMsgEditWindowPrivate *priv;
4180 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
4181 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4183 return priv->msg_uid;
4187 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
4188 ModestMsgEditWindowWidgetType widget_type)
4190 ModestMsgEditWindowPrivate *priv;
4192 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
4193 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
4195 switch (widget_type) {
4196 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
4197 return priv->msg_body;
4199 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
4200 return priv->to_field;
4202 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
4203 return priv->cc_field;
4205 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
4206 return priv->bcc_field;
4208 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
4209 return priv->subject_field;
4211 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
4212 return priv->attachments_view;
4220 remove_tags (WPTextBuffer *buffer)
4222 GtkTextIter start, end;
4224 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
4225 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
4227 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
4231 on_account_removed (TnyAccountStore *account_store,
4232 TnyAccount *account,
4235 /* Do nothing if it's a store account, because we use the
4236 transport to send the messages */
4237 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
4238 const gchar *parent_acc = NULL;
4239 const gchar *our_acc = NULL;
4241 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
4242 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
4243 /* Close this window if I'm showing a message of the removed account */
4244 if (strcmp (parent_acc, our_acc) == 0)
4245 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
4250 update_signature (ModestMsgEditWindow *self,
4251 const gchar *old_account,
4252 const gchar *new_account)
4254 ModestMsgEditWindowPrivate *priv;
4255 gboolean has_old_signature, has_new_signature;
4257 ModestAccountMgr *mgr;
4260 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4262 gtk_text_buffer_begin_user_action (priv->text_buffer);
4264 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
4265 mgr = modest_runtime_get_account_mgr ();
4269 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
4270 if (has_old_signature) {
4271 GtkTextIter match_start, match_end;
4273 MODEST_TEXT_UTILS_SIGNATURE_MARKER as it
4274 seems that the search has some problems
4275 with the blank space at the end */
4276 if (gtk_text_iter_forward_search (&iter, "--",
4277 GTK_TEXT_SEARCH_TEXT_ONLY,
4278 &match_start, NULL, NULL)) {
4279 gtk_text_buffer_get_end_iter (priv->text_buffer ,&match_end);
4280 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
4282 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
4283 &match_start, &match_end, NULL)) {
4287 gtk_text_buffer_get_end_iter (priv->text_buffer, &iter);
4292 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
4293 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
4294 if (has_new_signature) {
4297 gchar *full_signature = g_strconcat ((gtk_text_iter_starts_line (&iter)) ? "" : "\n",
4298 MODEST_TEXT_UTILS_SIGNATURE_MARKER, "\n",
4300 is_rich = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
4302 WPTextBufferFormat *fmt;
4303 GdkColor style_color;
4304 if (!gtk_style_lookup_color (GTK_WIDGET (self)->style, "SecondaryTextColor", &style_color)) {
4305 gdk_color_parse ("grey", &style_color);
4307 fmt = g_new0 (WPTextBufferFormat, 1);
4308 fmt->color = style_color;
4309 fmt->cs.color = 0x1;
4310 wp_text_buffer_insert_with_attribute (WP_TEXT_BUFFER (priv->text_buffer), &iter,
4314 g_free (full_signature);
4316 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4320 gtk_text_buffer_end_user_action (priv->text_buffer);
4323 static void update_branding (ModestMsgEditWindow *self,
4324 const gchar *new_account)
4326 ModestMsgEditWindowPrivate *priv;
4327 ModestAccountMgr *mgr;
4328 const GdkPixbuf *new_icon = NULL;
4329 gchar *new_label = NULL;
4330 gboolean show = FALSE;
4332 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4334 mgr = modest_runtime_get_account_mgr ();
4336 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4338 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4339 gtk_widget_show (priv->brand_icon);
4342 gtk_widget_hide (priv->brand_icon);
4345 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4346 gtk_widget_show (priv->brand_label);
4350 gtk_widget_hide (priv->brand_label);
4354 gtk_widget_show (priv->brand_container);
4356 gtk_widget_hide (priv->brand_container);
4360 from_field_changed (GtkWidget *button,
4361 ModestMsgEditWindow *self)
4363 ModestMsgEditWindowPrivate *priv;
4364 gchar *old_account, *new_account;
4366 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4368 old_account = priv->last_from_account;
4369 new_account = modest_selector_get_active_id (priv->from_field);
4372 g_warning ("%s, could not get the new account", __FUNCTION__);
4376 /* If the From is the same do nothing */
4377 if (old_account && new_account && !strcmp (old_account, new_account))
4380 priv->last_from_account = new_account;
4382 update_signature (self, old_account, new_account);
4383 update_branding (self, new_account);
4387 typedef struct _MessageSettingsHelper {
4388 ModestMsgEditWindow *window;
4389 GSList *priority_group;
4390 GSList *format_group;
4391 GtkToggleButton *current_priority;
4392 GtkToggleButton *current_format;
4393 } MessageSettingsHelper;
4396 on_priority_toggle (GtkToggleButton *button,
4397 MessageSettingsHelper *helper)
4400 ModestMsgEditWindowPrivate *priv;
4402 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4403 if (gtk_toggle_button_get_active (button)) {
4405 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4406 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4407 if ((node_button != button) &&
4408 gtk_toggle_button_get_active (node_button)) {
4409 gtk_toggle_button_set_active (node_button, FALSE);
4412 helper->current_priority = button;
4414 gboolean found = FALSE;
4415 /* If no one is active, activate it again */
4416 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4417 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4418 if (gtk_toggle_button_get_active (node_button)) {
4424 gtk_toggle_button_set_active (button, TRUE);
4430 on_format_toggle (GtkToggleButton *button,
4431 MessageSettingsHelper *helper)
4434 ModestMsgEditWindowPrivate *priv;
4436 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4437 if (gtk_toggle_button_get_active (button)) {
4439 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4440 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4441 if ((node_button != button) &&
4442 gtk_toggle_button_get_active (node_button)) {
4443 gtk_toggle_button_set_active (node_button, FALSE);
4446 helper->current_format = button;
4448 gboolean found = FALSE;
4449 /* If no one is active, activate it again */
4450 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4451 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4452 if (gtk_toggle_button_get_active (node_button)) {
4458 gtk_toggle_button_set_active (button, TRUE);
4465 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4470 GtkWidget *priority_hbox;
4471 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4472 GtkWidget *captioned;
4473 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4474 GtkWidget *format_hbox;
4475 GtkWidget *html_toggle, *text_toggle;
4476 ModestMsgEditWindowPrivate *priv;
4477 MessageSettingsHelper helper = {0,};
4479 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4480 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4481 helper.window = window;
4482 helper.priority_group = NULL;
4483 helper.format_group = NULL;
4485 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4486 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4488 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4489 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4490 _HL_DONE, GTK_RESPONSE_ACCEPT, NULL);
4491 vbox = gtk_vbox_new (FALSE, 0);
4492 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4493 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4494 gtk_container_add (GTK_CONTAINER (align), vbox);
4495 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4496 gtk_widget_show (align);
4497 gtk_widget_show (vbox);
4499 /* Priority toggles */
4500 priority_hbox = gtk_hbox_new (TRUE, 0);
4501 #ifdef MODEST_TOOLKIT_HILDON2
4502 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4504 high_toggle = gtk_toggle_button_new ();
4506 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4507 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4508 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4509 #ifdef MODEST_TOOLKIT_HILDON2
4510 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4512 medium_toggle = gtk_toggle_button_new ();
4514 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4515 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4516 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4517 #ifdef MODEST_TOOLKIT_HILDON2
4518 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4520 low_toggle = gtk_toggle_button_new ();
4522 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4523 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4524 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4525 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4526 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4527 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4528 gtk_widget_show_all (priority_hbox);
4529 captioned = modest_toolkit_utils_create_captioned (title_sizegroup, value_sizegroup,
4530 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4531 gtk_widget_show (captioned);
4532 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4534 /* format toggles */
4535 format_hbox = gtk_hbox_new (TRUE, 0);
4536 #ifdef MODEST_TOOLKIT_HILDON2
4537 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4539 html_toggle = gtk_toggle_button_new ();
4541 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4542 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4543 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4544 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4545 #ifdef MODEST_TOOLKIT_HILDON2
4546 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4548 text_toggle = gtk_toggle_button_new ();
4550 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4551 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4552 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4553 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4554 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4555 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4556 gtk_widget_show_all (format_hbox);
4557 gtk_widget_show (format_hbox);
4558 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4561 g_object_unref (title_sizegroup);
4562 g_object_unref (value_sizegroup);
4564 /* Set current values */
4565 switch (priv->priority_flags) {
4566 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4567 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4568 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4570 case TNY_HEADER_FLAG_LOW_PRIORITY:
4571 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4572 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4575 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4576 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4580 switch (modest_msg_edit_window_get_format (window)) {
4581 case MODEST_MSG_EDIT_FORMAT_TEXT:
4582 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4583 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4585 case MODEST_MSG_EDIT_FORMAT_HTML:
4587 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4588 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4592 /* Signal connects */
4593 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4594 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4595 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4596 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4597 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4599 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4600 GTK_WINDOW (dialog), GTK_WINDOW (window));
4602 /* Save settings if the user clicked on done */
4603 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4604 TnyHeaderFlags flags;
4605 ModestMsgEditFormat old_format, new_format;
4607 /* Set priority flags */
4608 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4609 if (priv->priority_flags != flags)
4610 modest_msg_edit_window_set_priority_flags (window, flags);
4612 /* Set edit format */
4613 old_format = modest_msg_edit_window_get_format (window);
4614 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4615 if (old_format != new_format) {
4616 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4617 modest_msg_edit_window_set_file_format (window, file_format);
4621 gtk_widget_destroy (dialog);
4622 g_slist_free (helper.priority_group);
4626 on_message_settings (GtkAction *action,
4627 ModestMsgEditWindow *window)
4629 modest_msg_edit_window_show_msg_settings_dialog (window);
4633 on_show_toolbar_button_toggled (GtkWidget *button,
4634 ModestMsgEditWindow *window)
4636 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4638 modest_msg_edit_window_show_toolbar (MODEST_WINDOW (window),
4639 modest_togglable_get_active (button));
4643 on_cc_button_toggled (GtkWidget *button,
4644 ModestMsgEditWindow *window)
4646 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4648 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4649 modest_togglable_get_active (button));
4653 on_bcc_button_toggled (GtkWidget *button,
4654 ModestMsgEditWindow *window)
4656 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4658 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4659 modest_togglable_get_active (button));
4663 setup_menu (ModestMsgEditWindow *self)
4665 ModestMsgEditWindowPrivate *priv = NULL;
4667 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4669 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4671 /* Settings menu buttons */
4672 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4673 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_check_names),
4675 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_viewer_addtocontacts"), NULL,
4676 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_add_to_contacts),
4677 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_add_to_contacts));
4678 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4679 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_undo),
4680 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4682 priv->cc_button = modest_toolkit_factory_create_check_menu (modest_runtime_get_toolkit_factory (),
4683 _("mcen_me_editor_showcc"));
4684 modest_togglable_set_active (priv->cc_button,
4686 modest_window_add_item_to_menu (MODEST_WINDOW (self), priv->cc_button, NULL);
4687 gtk_widget_show (priv->cc_button);
4688 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4689 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4691 priv->bcc_button = modest_toolkit_factory_create_check_menu (modest_runtime_get_toolkit_factory (),
4692 _("mcen_me_editor_showbcc"));
4693 gtk_widget_show (priv->bcc_button);
4694 modest_togglable_set_active (priv->bcc_button,
4696 modest_window_add_item_to_menu (MODEST_WINDOW (self), priv->bcc_button,
4698 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4699 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4701 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4702 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4703 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4704 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4705 MODEST_WINDOW_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4707 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4708 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4709 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4710 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_message_settings"), NULL,
4711 MODEST_WINDOW_MENU_CALLBACK (on_message_settings),
4713 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4714 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4717 priv->show_toolbar_button = modest_toolkit_factory_create_check_menu (modest_runtime_get_toolkit_factory (),
4718 _("mcen_bd_show_toolbar"));
4719 modest_togglable_set_active (priv->show_toolbar_button,
4721 modest_window_add_item_to_menu (MODEST_WINDOW (self), priv->show_toolbar_button,
4722 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_show_toolbar));
4723 gtk_widget_show (priv->show_toolbar_button);
4724 g_signal_connect (G_OBJECT (priv->show_toolbar_button), "toggled",
4725 G_CALLBACK (on_show_toolbar_button_toggled), (gpointer) self);
4730 emit_open_addressbook (GtkButton *button,
4731 ModestRecptEditor *editor)
4733 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4737 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4738 const gchar *label, GtkWidget *control)
4740 GtkWidget *abook_button;
4743 GtkWidget *label_widget;
4745 box = gtk_hbox_new (FALSE, 0);
4747 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4748 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4750 #ifdef MODEST_TOOLKIT_HILDON2
4751 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4753 abook_button = gtk_button_new ();
4755 label_widget = gtk_label_new (label);
4756 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4757 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4759 gtk_container_add (GTK_CONTAINER (align), abook_button);
4760 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4761 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4762 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4763 if (title_size_group)
4764 gtk_size_group_add_widget (title_size_group, label_widget);
4765 if (value_size_group)
4766 gtk_size_group_add_widget (value_size_group, control);
4768 g_signal_connect (G_OBJECT (abook_button), "clicked",
4769 G_CALLBACK (emit_open_addressbook), control);
4775 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4777 ModestMsgEditWindowPrivate *priv = NULL;
4779 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4781 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4782 priv->max_chars_banner = NULL;
4786 has_pending_addresses (ModestRecptEditor *recpt_editor)
4788 const gchar *recipients = NULL;
4789 GSList *start_indexes = NULL, *end_indexes = NULL;
4790 GSList *current_start, *current_end;
4791 GtkTextBuffer *buffer;
4792 gint offset_delta = 0;
4794 gboolean has_recipients_to_add = FALSE;
4796 recipients = modest_recpt_editor_get_recipients (recpt_editor);
4797 last_length = g_utf8_strlen (recipients, -1);
4798 modest_text_utils_get_addresses_indexes (recipients, &start_indexes, &end_indexes);
4803 current_start = start_indexes;
4804 current_end = end_indexes;
4805 buffer = modest_recpt_editor_get_buffer (recpt_editor);
4807 while (current_start && !has_recipients_to_add) {
4809 gchar *start_ptr, *end_ptr;
4810 gint start_pos, end_pos;
4812 start_pos = (*((gint*) current_start->data)) + offset_delta;
4813 end_pos = (*((gint*) current_end->data)) + offset_delta;
4815 start_ptr = g_utf8_offset_to_pointer (recipients, start_pos);
4816 end_ptr = g_utf8_offset_to_pointer (recipients, end_pos);
4818 address = g_strstrip (g_strndup (start_ptr, end_ptr - start_ptr));
4820 if (modest_text_utils_validate_recipient (address, NULL)) {
4821 if (!modest_address_book_has_address (address)) {
4822 has_recipients_to_add = TRUE;
4825 current_start = g_slist_next (current_start);
4826 current_end = g_slist_next (current_end);
4828 return has_recipients_to_add;
4832 modest_msg_edit_window_has_pending_addresses (ModestMsgEditWindow *self)
4834 ModestMsgEditWindowPrivate *priv = NULL;
4836 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self), FALSE);
4838 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4840 if (!has_pending_addresses ((ModestRecptEditor *) priv->to_field) &&
4841 !has_pending_addresses ((ModestRecptEditor *) priv->cc_field) &&
4842 !has_pending_addresses ((ModestRecptEditor *) priv->bcc_field))