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 priv->scrollable = modest_toolkit_factory_create_scrollable (modest_runtime_get_toolkit_factory ());
1062 g_object_set (G_OBJECT (priv->scrollable), "horizontal-policy", GTK_POLICY_NEVER, NULL);
1064 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
1065 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1066 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), MODEST_MARGIN_HALF, 0,
1067 MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
1069 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
1070 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
1071 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
1073 modest_scrollable_add_with_viewport (MODEST_SCROLLABLE (priv->scrollable), window_align);
1074 gtk_widget_show_all (GTK_WIDGET(priv->scrollable));
1076 window_box = gtk_vbox_new (FALSE, 0);
1077 gtk_container_add (GTK_CONTAINER(obj), window_box);
1079 gtk_box_pack_start (GTK_BOX (window_box), priv->scrollable, TRUE, TRUE, 0);
1081 /* Set window icon */
1082 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
1084 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1085 g_object_unref (window_icon);
1090 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
1092 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1094 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1095 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1096 priv->clipboard_change_handler_id))
1097 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1098 priv->clipboard_change_handler_id);
1099 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1100 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1101 priv->default_clipboard_change_handler_id))
1102 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1103 priv->default_clipboard_change_handler_id);
1105 if (priv->account_removed_handler_id &&
1106 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1107 priv->account_removed_handler_id))
1108 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1109 priv->account_removed_handler_id);
1113 modest_msg_edit_window_finalize (GObject *obj)
1115 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1117 if (priv->max_chars_banner) {
1118 g_object_weak_unref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, obj);
1119 priv->max_chars_banner = FALSE;
1122 /* Sanity check: shouldn't be needed, the window mgr should
1123 call this function before */
1124 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1126 if (priv->font_dialog != NULL) {
1127 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1130 if (priv->clipboard_text != NULL) {
1131 g_free (priv->clipboard_text);
1132 priv->clipboard_text = NULL;
1135 if (priv->draft_msg != NULL) {
1136 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1137 if (TNY_IS_HEADER (header)) {
1138 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1139 modest_window_mgr_unregister_header (mgr, header);
1141 g_object_unref (priv->draft_msg);
1142 priv->draft_msg = NULL;
1144 if (priv->outbox_msg != NULL) {
1145 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1146 if (TNY_IS_HEADER (header)) {
1147 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1148 modest_window_mgr_unregister_header (mgr, header);
1150 g_object_unref (priv->outbox_msg);
1151 priv->outbox_msg = NULL;
1153 if (priv->correct_scroll_idle > 0) {
1154 g_source_remove (priv->correct_scroll_idle);
1155 priv->correct_scroll_idle = 0;
1157 if (priv->scroll_drag_timeout_id > 0) {
1158 g_source_remove (priv->scroll_drag_timeout_id);
1159 priv->scroll_drag_timeout_id = 0;
1161 if (priv->clipboard_owner_idle > 0) {
1162 g_source_remove (priv->clipboard_owner_idle);
1163 priv->clipboard_owner_idle = 0;
1165 if (priv->original_account_name)
1166 g_free (priv->original_account_name);
1167 if (priv->original_mailbox)
1168 g_free (priv->original_mailbox);
1169 g_free (priv->msg_uid);
1170 g_free (priv->last_search);
1171 g_slist_free (priv->font_items_group);
1172 g_free (priv->references);
1173 g_free (priv->in_reply_to);
1174 g_object_unref (priv->attachments);
1175 g_object_unref (priv->images);
1177 /* This had to stay alive for as long as the picker that used it: */
1178 modest_pair_list_free (priv->from_field_protos);
1180 G_OBJECT_CLASS(parent_class)->finalize (obj);
1184 pixbuf_size_prepared (GdkPixbufLoader *loader,
1187 ModestMsgEditWindow *self)
1189 gint new_height, new_width;
1192 new_height = height;
1196 if (width > IMAGE_MAX_WIDTH) {
1197 new_height = height * IMAGE_MAX_WIDTH / width;
1198 new_width = IMAGE_MAX_WIDTH;
1201 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1205 pixbuf_from_stream (TnyStream *stream,
1206 const gchar *mime_type,
1207 guint64 *stream_size,
1208 ModestMsgEditWindow *self)
1210 GdkPixbufLoader *loader;
1213 GError *error = NULL;
1217 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1219 if (loader == NULL) {
1224 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1226 modest_window_show_progress (MODEST_WINDOW (self), TRUE);
1228 tny_stream_reset (TNY_STREAM (stream));
1229 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1230 unsigned char read_buffer[128];
1232 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1234 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1237 /* Allow some UI responsiveness */
1238 while (gtk_events_pending ())
1239 gtk_main_iteration ();
1241 modest_window_show_progress (MODEST_WINDOW (self), FALSE);
1243 gdk_pixbuf_loader_close (loader, &error);
1246 g_error_free (error);
1247 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1249 g_object_ref (pixbuf);
1250 g_object_unref (loader);
1255 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1256 GdkPixbuf *new_pixbuf;
1258 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1259 gdk_pixbuf_get_width (pixbuf);
1260 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1261 g_object_unref (pixbuf);
1262 pixbuf = new_pixbuf;
1266 *stream_size = size;
1272 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1274 ModestMsgEditWindowPrivate *priv;
1277 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1279 g_object_ref (self);
1280 for (iter = tny_list_create_iterator (attachments);
1281 !tny_iterator_is_done (iter);
1282 tny_iterator_next (iter)) {
1283 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1284 const gchar *cid = tny_mime_part_get_content_id (part);
1285 const gchar *mime_type = tny_mime_part_get_content_type (part);
1286 if ((cid != NULL)&&(mime_type != NULL)) {
1287 guint64 stream_size;
1288 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1289 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1292 g_object_unref (stream);
1294 if (pixbuf != NULL) {
1295 priv->images_count ++;
1296 priv->images_size += stream_size;
1297 #ifndef MODEST_HAVE_LIBWPEDITOR_PLUS
1298 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1300 g_object_unref (pixbuf);
1303 g_object_unref (part);
1305 g_object_unref (iter);
1306 g_object_unref (self);
1310 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1312 TnyMimePart *parent = NULL;
1313 const gchar *content_type = NULL;
1314 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1316 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1318 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1319 parent = g_object_ref (msg);
1320 } else if (content_type && !g_ascii_strcasecmp (content_type, "multipart/mixed")) {
1321 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1324 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1325 iter = tny_list_create_iterator (parts);
1326 while (!tny_iterator_is_done (iter)) {
1328 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1329 content_type = tny_mime_part_get_content_type (part);
1330 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1334 g_object_unref (part);
1336 tny_iterator_next (iter);
1338 g_object_unref (iter);
1339 g_object_unref (parts);
1342 if (parent != NULL) {
1343 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1346 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1347 iter = tny_list_create_iterator (parts);
1348 while (!tny_iterator_is_done (iter)) {
1350 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1351 content_type = tny_mime_part_get_content_type (part);
1352 if (content_type && g_str_has_prefix (content_type, "image/")) {
1353 tny_list_prepend (priv->images, (GObject *) part);
1355 g_object_unref (part);
1356 tny_iterator_next (iter);
1358 g_object_unref (iter);
1359 g_object_unref (parts);
1360 g_object_unref (parent);
1365 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1368 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1370 for (iter = tny_list_create_iterator (attachments) ;
1371 !tny_iterator_is_done (iter);
1372 tny_iterator_next (iter)) {
1373 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1374 const gchar *cid = tny_mime_part_get_content_id (part);
1376 char *invalid = NULL;
1377 gint int_cid = strtol (cid, &invalid, 10);
1378 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1379 priv->next_cid = int_cid + 1;
1382 g_object_unref (part);
1384 g_object_unref (iter);
1388 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1391 gchar *to, *cc, *bcc, *subject;
1393 ModestMsgEditWindowPrivate *priv;
1394 ModestWindowPrivate *parent_priv;
1396 TnyHeaderFlags priority_flags;
1397 TnyFolder *msg_folder;
1398 gboolean is_html = FALSE;
1399 gboolean field_view_set;
1401 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1402 g_return_if_fail (TNY_IS_MSG (msg));
1404 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1405 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1407 header = tny_msg_get_header (msg);
1408 to = tny_header_dup_to (header);
1409 cc = tny_header_dup_cc (header);
1410 bcc = tny_header_dup_bcc (header);
1411 subject = tny_header_dup_subject (header);
1413 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1414 priority_flags = tny_header_get_priority (header);
1417 gchar *quoted_names = modest_text_utils_quote_names (to);
1418 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), quoted_names);
1419 g_free (quoted_names);
1422 field_view_set = TRUE;
1424 gchar *quoted_names = modest_text_utils_quote_names (cc);
1425 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), quoted_names);
1426 g_free (quoted_names);
1427 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1428 gtk_widget_show (priv->cc_caption);
1429 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1430 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1431 gtk_widget_hide (priv->cc_caption);
1432 field_view_set = FALSE;
1434 modest_togglable_set_active (priv->cc_button, field_view_set);
1436 field_view_set = TRUE;
1438 gchar *quoted_names = modest_text_utils_quote_names (bcc);
1439 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), quoted_names);
1440 g_free (quoted_names);
1441 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1442 gtk_widget_show (priv->bcc_caption);
1443 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1444 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1445 gtk_widget_hide (priv->bcc_caption);
1446 field_view_set = FALSE;
1448 modest_togglable_set_active (priv->bcc_button, field_view_set);
1452 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1453 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1456 update_window_title (self);
1458 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1459 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1461 if ((body == NULL)||(body[0] == '\0')) {
1463 body = modest_text_utils_convert_to_html ("");
1466 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1467 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1470 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1473 /* Add attachments to the view */
1474 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1475 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1476 if (tny_list_get_length (priv->attachments) == 0) {
1477 gtk_widget_hide (priv->attachments_caption);
1479 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1480 gtk_widget_show_all (priv->attachments_caption);
1482 get_related_images (self, msg);
1483 update_next_cid (self, priv->attachments);
1484 update_next_cid (self, priv->images);
1485 replace_with_images (self, priv->images);
1487 if (preserve_is_rich && !is_html) {
1488 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1489 /* Get the default format required from configuration */
1490 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1491 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1494 /* Set the default focus depending on having already a To: field or not */
1495 if ((!to)||(*to == '\0')) {
1496 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1498 gtk_widget_grab_focus (priv->msg_body);
1501 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1503 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1504 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1506 modest_msg_edit_window_set_modified (self, FALSE);
1508 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1509 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1510 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1511 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1513 if (priv->msg_uid) {
1514 g_free (priv->msg_uid);
1515 priv->msg_uid = NULL;
1518 /* we should set a reference to the incoming message if it is a draft */
1519 msg_folder = tny_msg_get_folder (msg);
1521 if (modest_tny_folder_is_local_folder (msg_folder)) {
1522 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1523 if (type == TNY_FOLDER_TYPE_INVALID)
1524 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1526 if (type == TNY_FOLDER_TYPE_DRAFTS)
1527 priv->draft_msg = g_object_ref(msg);
1528 if (type == TNY_FOLDER_TYPE_OUTBOX)
1529 priv->outbox_msg = g_object_ref(msg);
1530 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1532 g_object_unref (msg_folder);
1541 #ifndef MODEST_TOOLKIT_HILDON2
1543 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1546 GList *item_children, *node;
1547 GtkWidget *bin_child;
1549 bin_child = gtk_bin_get_child (GTK_BIN(item));
1551 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1553 for (node = item_children; node != NULL; node = g_list_next (node)) {
1554 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1555 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1558 g_list_free (item_children);
1562 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1565 GList *item_children, *node;
1567 box = gtk_bin_get_child (GTK_BIN (item));
1568 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1569 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1571 for (node = item_children; node != NULL; node = g_list_next (node)) {
1572 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1573 if (GTK_IS_TOGGLE_BUTTON (node->data))
1574 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1575 else if (GTK_IS_BUTTON (node->data))
1576 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1578 g_list_free (item_children);
1583 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1585 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1586 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1587 GtkWidget *placeholder;
1588 GtkWidget *tool_item;
1593 GtkWidget *sizes_menu;
1597 #ifndef MODEST_TOOLKIT_HILDON2
1598 GSList *radio_group, *node;
1599 GtkWidget *fonts_menu;
1603 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1604 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1605 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar),
1606 #ifdef MODEST_TOOLKIT_HILDON2
1607 HILDON_ICON_SIZE_FINGER
1609 GTK_ICON_SIZE_LARGE_TOOLBAR
1612 modest_window_add_toolbar (MODEST_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1614 /* Font color placeholder */
1615 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1616 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1619 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1620 #ifdef MODEST_TOOLKIT_HILDON2
1621 priv->font_color_button = modest_color_button_new ();
1623 priv->font_color_button = gtk_color_button_new ();
1625 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1626 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1627 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1628 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1629 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1630 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1631 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1632 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1634 G_CALLBACK (modest_msg_edit_window_color_button_change),
1637 /* Font size and face placeholder */
1638 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1639 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1641 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, ""));
1642 priv->size_tool_button_label = gtk_label_new (NULL);
1643 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1644 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1645 size_text, "</span>", NULL);
1646 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1647 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1649 #ifdef MODEST_TOOLKIT_HILDON2
1650 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1652 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1653 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1654 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1655 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1656 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1657 gtk_widget_set_sensitive (arrow, FALSE);
1658 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1659 sizes_menu = gtk_menu_new ();
1660 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1661 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1664 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1665 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1667 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1671 if (wp_font_size[size_index] == 12)
1672 priv->current_size_index = size_index;
1676 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1677 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1678 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1679 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1680 priv->font_size_toolitem = tool_item;
1682 #ifdef MODEST_TOOLKIT_HILDON2
1684 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, ""));
1685 priv->font_tool_button_label = gtk_label_new (NULL);
1686 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1687 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1688 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1690 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1691 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1692 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1693 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1694 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1695 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1696 gtk_widget_set_sensitive (arrow, FALSE);
1697 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1699 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1700 priv->font_tool_button_label = gtk_label_new (NULL);
1701 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1702 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1704 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1705 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1706 gtk_widget_show (priv->font_tool_button_label);
1707 gtk_widget_show (GTK_WIDGET (tool_item));
1708 fonts_menu = gtk_menu_new ();
1711 #ifdef MODEST_TOOLKIT_HILDON2
1712 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1713 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1716 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1718 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1719 0, wp_get_font_name (font_index),
1722 if (font_index == DEFAULT_FONT)
1723 priv->current_face_index = font_index;
1725 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1726 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1727 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1728 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1729 priv->font_face_toolitem = tool_item;
1731 priv->font_items_group = NULL;
1733 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1734 GtkWidget *font_menu_item;
1735 GtkWidget *child_label;
1737 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1738 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1739 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1740 wp_get_font_name (font_index), "</span>", NULL);
1741 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1744 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1745 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1746 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1747 gtk_widget_show (font_menu_item);
1749 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1752 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1753 GtkWidget *item = (GtkWidget *) node->data;
1754 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1757 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1758 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1759 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1760 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1761 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1762 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1763 priv->font_face_toolitem = tool_item;
1766 /* Set expand and homogeneous for remaining items */
1767 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1768 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1769 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1770 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1771 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1772 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1773 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsInsertImage");
1774 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1775 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1777 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1778 will not show the tool items added to the placeholders) */
1779 gtk_widget_show_all (parent_priv->toolbar);
1781 /* Set the no show all *after* showing all items. We do not
1782 want the toolbar to be shown with a show all because it
1783 could go against the gconf setting regarding showing or not
1784 the toolbar of the editor window */
1785 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1791 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1794 ModestWindowPrivate *parent_priv;
1795 ModestMsgEditWindowPrivate *priv;
1796 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1797 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1798 ModestWindowMgr *mgr = NULL;
1800 g_return_val_if_fail (msg, NULL);
1801 g_return_val_if_fail (account_name, NULL);
1803 mgr = modest_runtime_get_window_mgr ();
1805 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1807 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1808 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1810 /* Menubar. Update the state of some toggles */
1811 priv->from_field_protos = get_transports ();
1812 priv->original_mailbox = NULL;
1813 modest_selector_set_pair_list (priv->from_field, priv->from_field_protos);
1814 modest_selector_set_active_id (priv->from_field, (gpointer) account_name);
1815 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
1816 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1817 modest_selector_set_active_id (priv->from_field, (gpointer) mailbox);
1818 priv->original_mailbox = g_strdup (mailbox);
1819 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1820 /* We set the first mailbox as the active mailbox */
1821 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1822 if (priv->original_mailbox != NULL)
1823 modest_selector_set_active_id (priv->from_field,
1824 (gpointer) priv->original_mailbox);
1826 modest_selector_set_active_id (priv->from_field,
1827 (gpointer) account_name);
1829 modest_selector_set_active_id (priv->from_field, (gpointer) account_name);
1831 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
1832 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1833 if (!GTK_IS_COMBO_BOX (priv->from_field)) {
1834 #ifdef HILDON_TOOLKIT_HILDON2
1835 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1837 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1838 hildon_touch_selector_get_current_text
1839 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1842 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1843 modest_window_add_toolbar (MODEST_WINDOW (obj), GTK_TOOLBAR (priv->isearch_toolbar));
1846 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1848 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1850 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1851 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1853 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1855 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1856 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1857 /* Add common dimming rules */
1858 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1859 modest_msg_edit_window_toolbar_dimming_entries,
1860 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1861 MODEST_WINDOW (obj));
1862 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1863 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1864 MODEST_WINDOW (obj));
1865 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1866 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1867 MODEST_WINDOW (obj));
1868 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1869 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1870 MODEST_WINDOW (obj));
1871 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1872 G_CALLBACK (modest_ui_dimming_rules_on_send),
1873 MODEST_WINDOW (obj));
1874 /* Insert dimming rules group for this window */
1875 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1876 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1878 /* Setup app menu */
1879 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1881 /* Checks the dimming rules */
1882 g_object_unref (toolbar_rules_group);
1883 g_object_unref (clipboard_rules_group);
1884 gtk_widget_hide (priv->priority_icon);
1885 gtk_widget_queue_resize (priv->subject_box);
1886 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1888 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1890 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1891 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1892 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1893 priv->update_caption_visibility = TRUE;
1895 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1897 /* Track account-removed signal, this window should be closed
1898 in the case we're creating a mail associated to the account
1900 priv->account_removed_handler_id =
1901 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1903 G_CALLBACK(on_account_removed),
1906 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1908 return (ModestWindow*) obj;
1912 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1914 GString **string_buffer = (GString **) user_data;
1916 *string_buffer = g_string_append (*string_buffer, buffer);
1922 * @result: A new string which should be freed with g_free().
1925 get_formatted_data (ModestMsgEditWindow *edit_window)
1927 ModestMsgEditWindowPrivate *priv;
1928 GString *string_buffer = g_string_new ("");
1930 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1932 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1934 modest_text_utils_hyperlinkify (string_buffer);
1936 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1938 return g_string_free (string_buffer, FALSE);
1943 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1946 const gchar *account_name;
1947 ModestMsgEditWindowPrivate *priv;
1948 TnyIterator *att_iter;
1949 const gchar *picker_active_id;
1951 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1953 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1955 picker_active_id = modest_selector_get_active_id (priv->from_field);
1956 g_return_val_if_fail (picker_active_id, NULL);
1957 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1959 /* don't free these (except from) */
1960 data = g_slice_new0 (MsgData);
1961 data->from = g_strdup ((gchar *) modest_selector_get_active_display_name (priv->from_field));
1962 data->account_name = g_strdup (account_name);
1963 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1964 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1965 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1966 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1967 data->references = g_strdup (priv->references);
1968 data->in_reply_to = g_strdup (priv->in_reply_to);
1969 if (priv->draft_msg) {
1970 data->draft_msg = g_object_ref (priv->draft_msg);
1971 } else if (priv->outbox_msg) {
1972 data->draft_msg = g_object_ref (priv->outbox_msg);
1974 data->draft_msg = NULL;
1977 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1979 gtk_text_buffer_get_bounds (buf, &b, &e);
1980 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1982 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1983 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1985 data->html_body = NULL;
1987 /* deep-copy the data */
1988 att_iter = tny_list_create_iterator (priv->attachments);
1989 data->attachments = NULL;
1990 while (!tny_iterator_is_done (att_iter)) {
1991 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1992 if (!(TNY_IS_MIME_PART(part))) {
1993 g_warning ("strange data in attachment list");
1994 g_object_unref (part);
1995 tny_iterator_next (att_iter);
1998 data->attachments = g_list_append (data->attachments,
2000 tny_iterator_next (att_iter);
2002 g_object_unref (att_iter);
2004 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
2005 att_iter = tny_list_create_iterator (priv->images);
2006 data->images = NULL;
2007 while (!tny_iterator_is_done (att_iter)) {
2008 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
2010 if (!(TNY_IS_MIME_PART(part))) {
2011 g_warning ("strange data in attachment list");
2012 g_object_unref (part);
2013 tny_iterator_next (att_iter);
2016 cid = tny_mime_part_get_content_id (part);
2018 gchar *image_tag_id;
2019 GtkTextTag *image_tag;
2021 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
2022 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
2023 g_free (image_tag_id);
2025 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
2027 ((gtk_text_iter_has_tag (&iter, image_tag))||
2028 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
2029 data->images = g_list_append (data->images,
2030 g_object_ref (part));
2032 g_object_unref (part);
2033 tny_iterator_next (att_iter);
2035 g_object_unref (att_iter);
2037 data->priority_flags = priv->priority_flags;
2044 unref_gobject (GObject *obj, gpointer data)
2046 if (!G_IS_OBJECT(obj))
2048 g_object_unref (obj);
2052 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
2055 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
2063 g_free (data->from);
2064 g_free (data->subject);
2065 g_free (data->plain_body);
2066 g_free (data->html_body);
2067 g_free (data->account_name);
2068 g_free (data->references);
2069 g_free (data->in_reply_to);
2071 if (data->draft_msg != NULL) {
2072 g_object_unref (data->draft_msg);
2073 data->draft_msg = NULL;
2076 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
2077 g_list_free (data->attachments);
2078 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
2079 g_list_free (data->images);
2081 g_slice_free (MsgData, data);
2085 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
2087 guint64 *parts_size)
2089 ModestMsgEditWindowPrivate *priv;
2091 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2093 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
2095 /* TODO: add images */
2096 *parts_size += priv->images_size;
2097 *parts_count += priv->images_count;
2102 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
2105 ModestMsgEditWindowPrivate *priv = NULL;
2106 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
2108 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2110 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2112 return MODEST_MSG_EDIT_FORMAT_HTML;
2114 return MODEST_MSG_EDIT_FORMAT_TEXT;
2118 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
2119 ModestMsgEditFormat format)
2121 ModestMsgEditWindowPrivate *priv;
2122 ModestWindowPrivate *parent_priv;
2124 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2125 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2126 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
2129 case MODEST_MSG_EDIT_FORMAT_HTML:
2130 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2131 update_signature (self, priv->last_from_account, priv->last_from_account);
2132 if (parent_priv->toolbar)
2133 on_show_toolbar_button_toggled (priv->show_toolbar_button,
2134 MODEST_MSG_EDIT_WINDOW (self));
2136 case MODEST_MSG_EDIT_FORMAT_TEXT:
2137 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2138 if (parent_priv->toolbar)
2139 on_show_toolbar_button_toggled (priv->show_toolbar_button,
2140 MODEST_MSG_EDIT_WINDOW (self));
2143 g_return_if_reached ();
2147 ModestMsgEditFormatState *
2148 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
2150 ModestMsgEditFormatState *format_state = NULL;
2151 ModestMsgEditWindowPrivate *priv;
2152 WPTextBufferFormat *buffer_format;
2154 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
2156 buffer_format = g_new0 (WPTextBufferFormat, 1);
2157 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2159 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
2161 format_state = g_new0 (ModestMsgEditFormatState, 1);
2162 format_state->bold = buffer_format->bold&0x1;
2163 format_state->italics = buffer_format->italic&0x1;
2164 format_state->bullet = buffer_format->bullet&0x1;
2165 format_state->color = buffer_format->color;
2166 format_state->font_size = buffer_format->font_size;
2167 format_state->font_family = wp_get_font_name (buffer_format->font);
2168 format_state->justification = buffer_format->justification;
2169 g_free (buffer_format);
2171 return format_state;
2176 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
2177 const ModestMsgEditFormatState *format_state)
2179 ModestMsgEditWindowPrivate *priv;
2180 WPTextBufferFormat *buffer_format;
2181 WPTextBufferFormat *current_format;
2183 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2184 g_return_if_fail (format_state != NULL);
2186 buffer_format = g_new0 (WPTextBufferFormat, 1);
2187 current_format = g_new0 (WPTextBufferFormat, 1);
2189 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2190 gtk_widget_grab_focus (priv->msg_body);
2191 buffer_format->bold = (format_state->bold != FALSE);
2192 buffer_format->italic = (format_state->italics != FALSE);
2193 buffer_format->color = format_state->color;
2194 buffer_format->font_size = format_state->font_size;
2195 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
2196 buffer_format->justification = format_state->justification;
2197 buffer_format->bullet = format_state->bullet;
2199 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2201 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2202 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2203 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2204 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2205 buffer_format->cs.font = (buffer_format->font != current_format->font);
2206 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2207 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2209 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2210 if (buffer_format->cs.bold) {
2211 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2212 GINT_TO_POINTER (buffer_format->bold&0x1));
2214 if (buffer_format->cs.italic) {
2215 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2216 GINT_TO_POINTER (buffer_format->italic&0x1));
2218 if (buffer_format->cs.color) {
2219 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2220 GINT_TO_POINTER (&(buffer_format->color)));
2222 if (buffer_format->cs.font_size) {
2223 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2224 GINT_TO_POINTER (buffer_format->font_size));
2226 if (buffer_format->cs.justification) {
2227 switch (buffer_format->justification) {
2228 case GTK_JUSTIFY_LEFT:
2229 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2230 GINT_TO_POINTER(TRUE));
2232 case GTK_JUSTIFY_CENTER:
2233 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2234 GINT_TO_POINTER(TRUE));
2236 case GTK_JUSTIFY_RIGHT:
2237 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2238 GINT_TO_POINTER(TRUE));
2245 if (buffer_format->cs.font) {
2246 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2247 GINT_TO_POINTER (buffer_format->font));
2249 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2250 if (buffer_format->cs.bullet) {
2251 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2252 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2254 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2256 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2258 g_free (buffer_format);
2259 g_free (current_format);
2261 /* Check dimming rules */
2262 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2263 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2267 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2269 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2271 ModestWindowPrivate *parent_priv;
2272 ModestMsgEditWindowPrivate *priv;
2274 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2275 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2277 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2278 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2279 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2280 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2282 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2283 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2284 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2287 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2289 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2290 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2292 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2293 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2295 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2296 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2299 switch (buffer_format->justification)
2301 case GTK_JUSTIFY_LEFT:
2302 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2304 case GTK_JUSTIFY_CENTER:
2305 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2307 case GTK_JUSTIFY_RIGHT:
2308 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2315 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2317 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2318 G_CALLBACK (modest_msg_edit_window_color_button_change),
2320 #ifdef MODEST_TOOLKIT_HILDON2
2321 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2323 gtk_color_button_set_color (GTK_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2325 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2326 G_CALLBACK (modest_msg_edit_window_color_button_change),
2329 if (priv->current_size_index != buffer_format->font_size) {
2333 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2334 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2338 priv->current_size_index = buffer_format->font_size;
2340 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2341 markup = g_strconcat ("<span font_family='Sans'>",
2342 size_text, "</span>", NULL);
2344 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2348 gtk_tree_path_free (path);
2351 #ifdef MODEST_TOOLKIT_HILDON2
2352 if (priv->current_face_index != buffer_format->font) {
2356 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2357 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2361 priv->current_face_index = buffer_format->font;
2362 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2363 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2364 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2371 GtkWidget *new_font_menuitem;
2372 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
2373 buffer_format->font))->data);
2374 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
2378 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2379 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2380 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2382 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2383 G_CALLBACK (modest_msg_edit_window_font_change),
2385 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2386 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2387 G_CALLBACK (modest_msg_edit_window_font_change),
2392 g_free (buffer_format);
2398 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2400 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2401 ModestMsgEditWindowPrivate *priv;
2402 GtkWidget *dialog = NULL;
2404 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2405 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2407 #ifdef MODEST_TOOLKIT_HILDON2
2408 dialog = hildon_color_chooser_new ();
2409 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2410 g_free (buffer_format);
2412 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2414 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2415 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2418 gtk_widget_destroy (dialog);
2420 dialog = gtk_color_selection_dialog_new (NULL);
2421 GtkWidget *selection;
2423 g_object_get (G_OBJECT (dialog), "color_selection", &selection, NULL);
2424 gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (selection), &(buffer_format->color));
2425 gtk_color_selection_set_previous_color (GTK_COLOR_SELECTION (selection), &(buffer_format->color));
2426 g_free (buffer_format);
2428 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2430 gtk_color_selection_get_current_color (GTK_COLOR_SELECTION(selection), &col);
2431 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2434 gtk_widget_destroy (dialog);
2441 create_stream_for_uri (const gchar* uri)
2446 TnyStream *result = NULL;
2448 GnomeVFSHandle *handle = NULL;
2449 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2450 if (test == GNOME_VFS_OK) {
2451 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2452 /* Streams over OBEX (Bluetooth) are not seekable but
2453 * we expect them to be (we might need to read them
2454 * several times). So if this is a Bluetooth URI just
2455 * read the whole file into memory (this is not a fast
2456 * protocol so we can assume that these files are not
2457 * going to be very big) */
2458 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2459 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2460 TnyStream *memstream = tny_camel_mem_stream_new ();
2461 tny_stream_write_to_stream (vfssstream, memstream);
2462 g_object_unref (vfssstream);
2465 result = vfssstream;
2473 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2476 ModestMsgEditWindowPrivate *priv;
2477 GtkWidget *dialog = NULL;
2479 GSList *uris = NULL;
2480 GSList *uri_node = NULL;
2482 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2484 dialog = modest_toolkit_factory_create_file_chooser_dialog (modest_runtime_get_toolkit_factory (),
2485 _("mcen_ia_select_inline_image_title"),
2486 (GtkWindow *) window,
2487 GTK_FILE_CHOOSER_ACTION_OPEN);
2488 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2490 #ifdef MODEST_TOOLKIT_HILDON2
2491 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2494 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2495 GTK_WINDOW (dialog), GTK_WINDOW (window));
2497 response = gtk_dialog_run (GTK_DIALOG (dialog));
2499 case GTK_RESPONSE_OK:
2501 gchar *current_folder;
2502 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2503 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2504 if (current_folder && current_folder != '\0') {
2506 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2507 current_folder, &err);
2509 g_debug ("Error storing latest used folder: %s", err->message);
2513 g_free (current_folder);
2519 gtk_widget_destroy (dialog);
2521 g_object_ref (window);
2522 /* The operation could take some time so allow the dialog to be closed */
2523 while (gtk_events_pending ())
2524 gtk_main_iteration ();
2526 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2528 GnomeVFSHandle *handle = NULL;
2529 GnomeVFSResult result;
2530 GtkTextIter position;
2531 GtkTextMark *insert_mark;
2533 uri = (const gchar *) uri_node->data;
2534 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2535 if (result == GNOME_VFS_OK) {
2537 GnomeVFSFileInfo *info;
2538 gchar *filename, *basename, *escaped_filename;
2539 TnyMimePart *mime_part;
2541 const gchar *mime_type = NULL;
2542 GnomeVFSURI *vfs_uri;
2543 guint64 stream_size;
2545 gnome_vfs_close (handle);
2546 vfs_uri = gnome_vfs_uri_new (uri);
2548 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2549 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2550 g_free (escaped_filename);
2551 gnome_vfs_uri_unref (vfs_uri);
2552 info = gnome_vfs_file_info_new ();
2554 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2555 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2557 mime_type = gnome_vfs_file_info_get_mime_type (info);
2559 mime_part = tny_platform_factory_new_mime_part
2560 (modest_runtime_get_platform_factory ());
2562 TnyStream *stream = create_stream_for_uri (uri);
2564 if (stream == NULL) {
2566 modest_platform_information_banner (NULL, NULL,
2567 _FM_OPENING_NOT_ALLOWED);
2569 g_object_unref (mime_part);
2570 gnome_vfs_file_info_unref (info);
2574 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2576 content_id = g_strdup_printf ("%d", priv->next_cid);
2577 tny_mime_part_set_content_id (mime_part, content_id);
2578 g_free (content_id);
2581 basename = g_path_get_basename (filename);
2582 tny_mime_part_set_filename (mime_part, basename);
2585 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2587 if (pixbuf != NULL) {
2588 priv->images_size += stream_size;
2589 priv->images_count ++;
2590 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2591 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2592 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2593 tny_mime_part_get_content_id (mime_part), pixbuf);
2594 g_object_unref (pixbuf);
2596 tny_list_prepend (priv->images, (GObject *) mime_part);
2597 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2599 modest_platform_information_banner (NULL, NULL,
2600 _("mail_ib_file_operation_failed"));
2604 g_object_unref (mime_part);
2605 gnome_vfs_file_info_unref (info);
2609 g_object_unref (window);
2613 on_attach_file_response (GtkDialog *dialog,
2617 GSList *uris = NULL;
2619 GnomeVFSFileSize total_size, allowed_size;
2620 ModestMsgEditWindow *window;
2621 ModestMsgEditWindowPrivate *priv;
2626 case GTK_RESPONSE_OK:
2628 gchar *current_folder;
2630 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2631 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2632 if (current_folder && current_folder != '\0') {
2634 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2635 current_folder, &err);
2637 g_debug ("Error storing latest used folder: %s", err->message);
2641 g_free (current_folder);
2648 window = MODEST_MSG_EDIT_WINDOW (user_data);
2649 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2651 /* allowed size is the maximum size - what's already there */
2652 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2653 &att_num, &att_size);
2654 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2657 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2659 const gchar *uri = (const gchar *) uri_node->data;
2662 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2664 if (total_size > allowed_size) {
2665 g_debug ("%s: total size: %u",
2666 __FUNCTION__, (unsigned int)total_size);
2669 allowed_size -= total_size;
2671 g_slist_foreach (uris, (GFunc) g_free, NULL);
2672 g_slist_free (uris);
2674 gtk_widget_destroy (GTK_WIDGET (dialog));
2678 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2680 GtkWidget *dialog = NULL;
2681 ModestMsgEditWindowPrivate *priv;
2684 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2686 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2688 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2691 dialog = modest_toolkit_factory_create_file_chooser_dialog (modest_runtime_get_toolkit_factory (),
2692 _("mcen_ia_select_attachment_title"),
2693 (GtkWindow *) window,
2694 GTK_FILE_CHOOSER_ACTION_OPEN);
2695 conf_folder = modest_conf_get_string (modest_runtime_get_conf (),
2696 MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2697 if (conf_folder && conf_folder[0] != '\0') {
2698 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2701 /* Set the default folder to documents folder */
2702 docs_folder = (gchar *) g_strdup(g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
2703 #ifdef MODEST_TOOLKIT_HILDON2
2706 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2707 ".documents", NULL);
2710 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2711 g_free (docs_folder);
2713 g_free (conf_folder);
2714 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2715 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2716 GTK_WINDOW (dialog), GTK_WINDOW (window));
2718 /* Connect to response & show */
2719 g_signal_connect (dialog, "response",
2720 G_CALLBACK (on_attach_file_response), window);
2721 gtk_widget_show (dialog);
2726 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2728 GnomeVFSFileSize allowed_size)
2731 GnomeVFSHandle *handle = NULL;
2732 ModestMsgEditWindowPrivate *priv;
2733 GnomeVFSResult result;
2734 GnomeVFSFileSize size = 0;
2735 g_return_val_if_fail (window, 0);
2736 g_return_val_if_fail (uri, 0);
2738 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2740 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2741 if (result == GNOME_VFS_OK) {
2742 TnyMimePart *mime_part;
2744 const gchar *mime_type = NULL;
2746 gchar *escaped_filename;
2749 GnomeVFSFileInfo *info;
2750 GnomeVFSURI *vfs_uri;
2752 gnome_vfs_close (handle);
2753 vfs_uri = gnome_vfs_uri_new (uri);
2756 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2757 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2758 g_free (escaped_filename);
2759 gnome_vfs_uri_unref (vfs_uri);
2761 info = gnome_vfs_file_info_new ();
2763 if (gnome_vfs_get_file_info (uri,
2765 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2767 mime_type = gnome_vfs_file_info_get_mime_type (info);
2768 mime_part = tny_platform_factory_new_mime_part
2769 (modest_runtime_get_platform_factory ());
2771 /* try to get the attachment's size; this may fail for weird
2772 * file systems, like obex, upnp... */
2773 if (allowed_size != 0 &&
2774 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2776 if (size > allowed_size) {
2777 modest_platform_information_banner (NULL, NULL,
2778 _("mail_ib_error_attachment_size"));
2783 g_debug ("%s: could not get attachment size", __FUNCTION__);
2785 stream = create_stream_for_uri (uri);
2787 if (stream == NULL) {
2789 modest_platform_information_banner (NULL, NULL, _FM_OPENING_NOT_ALLOWED);
2791 g_object_unref (mime_part);
2793 gnome_vfs_file_info_unref (info);
2797 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2798 g_object_unref (stream);
2800 content_id = g_strdup_printf ("%d", priv->next_cid);
2801 tny_mime_part_set_content_id (mime_part, content_id);
2802 g_free (content_id);
2805 basename = g_path_get_basename (filename);
2806 tny_mime_part_set_filename (mime_part, basename);
2809 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2810 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2812 info->size == 0, info->size);
2813 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2814 gtk_widget_show_all (priv->attachments_caption);
2815 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2817 g_object_unref (mime_part);
2818 gnome_vfs_file_info_unref (info);
2825 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2828 ModestMsgEditWindowPrivate *priv;
2831 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2832 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2834 if (att_list == NULL) {
2835 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2836 if (!modest_toolkit_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2837 g_object_unref (att_list);
2841 g_object_ref (att_list);
2844 if (tny_list_get_length (att_list) == 0) {
2845 modest_platform_system_banner (NULL, NULL, _("TODO: no attachments selected to remove"));
2847 gboolean dialog_response;
2848 gchar *message = NULL;
2849 gchar *filename = NULL;
2851 if (tny_list_get_length (att_list) == 1) {
2853 iter = tny_list_create_iterator (att_list);
2854 part = (TnyMimePart *) tny_iterator_get_current (iter);
2855 g_object_unref (iter);
2856 if (TNY_IS_MSG (part)) {
2857 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2859 filename = tny_header_dup_subject (header);
2860 g_object_unref (header);
2862 if (filename == NULL) {
2863 filename = g_strdup (_("mail_va_no_subject"));
2866 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2868 g_object_unref (part);
2870 filename = g_strdup ("");
2872 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2873 "emev_nc_delete_attachments",
2874 tny_list_get_length (att_list)), filename);
2877 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2881 if (dialog_response != GTK_RESPONSE_OK) {
2882 g_object_unref (att_list);
2886 for (iter = tny_list_create_iterator (att_list);
2887 !tny_iterator_is_done (iter);
2888 tny_iterator_next (iter)) {
2889 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2890 const gchar *att_id;
2891 tny_list_remove (priv->attachments, (GObject *) mime_part);
2893 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2895 if (tny_list_get_length (priv->attachments) == 0)
2896 gtk_widget_hide (priv->attachments_caption);
2897 att_id = tny_mime_part_get_content_id (mime_part);
2899 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2901 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2902 g_object_unref (mime_part);
2904 g_object_unref (iter);
2907 g_object_unref (att_list);
2909 /* if the last attachment has been removed, focus the Subject: field */
2910 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2911 gtk_widget_grab_focus (priv->subject_field);
2915 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2918 ModestMsgEditWindowPrivate *priv;
2921 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2923 gtk_color_button_get_color (GTK_COLOR_BUTTON(priv->font_color_button), &new_color);
2925 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) &new_color);
2927 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2930 #ifndef MODEST_TOOLKIT_HILDON2
2932 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2935 ModestMsgEditWindowPrivate *priv;
2936 gint new_font_index;
2937 ModestMsgEditWindow *window;
2940 window = MODEST_MSG_EDIT_WINDOW (userdata);
2941 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2942 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2944 if (gtk_check_menu_item_get_active (menu_item)) {
2947 label = gtk_bin_get_child (GTK_BIN (menu_item));
2949 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2951 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2952 GINT_TO_POINTER(new_font_index)))
2953 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2955 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2956 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2957 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2964 font_size_clicked (GtkToolButton *button,
2965 ModestMsgEditWindow *window)
2967 #ifdef MODEST_TOOLKIT_HILDON2
2968 ModestMsgEditWindowPrivate *priv;
2969 GtkWidget *selector, *dialog;
2971 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2973 selector = hildon_touch_selector_new ();
2974 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2975 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2977 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2978 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2979 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2981 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2985 WPTextBufferFormat format;
2987 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2989 memset (&format, 0, sizeof (format));
2990 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2992 format.cs.font_size = TRUE;
2993 format.cs.text_position = TRUE;
2994 format.cs.font = TRUE;
2995 format.font_size = new_index;
2996 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2998 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2999 GINT_TO_POINTER (new_index)))
3000 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
3002 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
3003 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
3004 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
3005 size_text, "</span>", NULL);
3007 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
3011 gtk_widget_destroy (dialog);
3013 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
3017 #ifdef MODEST_TOOLKIT_HILDON2
3019 font_face_clicked (GtkToolButton *button,
3020 ModestMsgEditWindow *window)
3022 ModestMsgEditWindowPrivate *priv;
3023 GtkWidget *selector, *dialog;
3024 GtkCellRenderer *renderer;
3026 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3028 selector = hildon_touch_selector_new ();
3029 renderer = gtk_cell_renderer_text_new ();
3030 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
3031 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
3032 renderer, "family", 0, "text", 0, NULL);
3033 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
3035 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
3036 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
3037 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
3039 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
3040 gint new_font_index;
3044 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
3045 path = gtk_tree_path_new_from_indices (new_font_index, -1);
3046 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
3050 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
3052 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
3053 GINT_TO_POINTER(new_font_index)))
3054 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
3056 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
3057 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
3059 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
3063 gtk_tree_path_free (path);
3066 gtk_widget_destroy (dialog);
3068 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
3073 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
3076 ModestMsgEditWindowPrivate *priv = NULL;
3077 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3079 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3080 if (!priv->update_caption_visibility)
3083 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
3085 gtk_widget_show (priv->cc_caption);
3087 gtk_widget_hide (priv->cc_caption);
3089 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
3093 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
3096 ModestMsgEditWindowPrivate *priv = NULL;
3097 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3099 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3100 if (!priv->update_caption_visibility)
3103 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
3105 gtk_widget_show (priv->bcc_caption);
3107 gtk_widget_hide (priv->bcc_caption);
3109 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
3113 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
3114 ModestRecptEditor *editor)
3116 ModestMsgEditWindowPrivate *priv;
3118 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3119 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
3121 /* we check for low-mem; in that case, show a warning, and don't allow
3122 * for the addressbook
3124 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3127 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3129 if (editor == NULL) {
3130 GtkWidget *view_focus, *parent;
3131 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
3133 /* This code should be kept in sync with ModestRecptEditor. The
3134 textview inside the recpt editor is the one that really gets the
3135 focus. As it's inside a scrolled window, and this one inside the
3136 hbox recpt editor inherits from, we'll need to go up in the
3137 hierarchy to know if the text view is part of the recpt editor
3138 or if it's a different text entry */
3139 parent = gtk_widget_get_parent (view_focus);
3140 if (parent && MODEST_IS_RECPT_EDITOR (parent))
3141 editor = MODEST_RECPT_EDITOR (parent);
3144 editor = MODEST_RECPT_EDITOR (priv->to_field);
3147 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
3151 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
3153 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3155 modest_msg_edit_window_open_addressbook (window, NULL);
3159 modest_msg_edit_window_show_toolbar (ModestWindow *self,
3160 gboolean show_toolbar)
3162 ModestWindowPrivate *parent_priv;
3163 ModestMsgEditWindowPrivate *priv;
3165 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
3166 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3167 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
3169 /* We can not just use the code of
3170 modest_msg_edit_window_setup_toolbar because it has a
3171 mixture of both initialization and creation code. */
3173 gint current_format;
3174 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3175 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3176 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3177 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3179 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
3182 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3184 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, show_toolbar, NULL);
3185 if (modest_togglable_get_active (priv->show_toolbar_button) != show_toolbar) {
3186 modest_togglable_set_active (priv->show_toolbar_button, show_toolbar);
3191 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
3192 TnyHeaderFlags priority_flags)
3194 ModestMsgEditWindowPrivate *priv;
3195 ModestWindowPrivate *parent_priv;
3197 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3199 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3200 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3202 if (priv->priority_flags != priority_flags) {
3203 GtkAction *priority_action = NULL;
3205 priv->priority_flags = priority_flags;
3207 switch (priority_flags) {
3208 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3209 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3210 MODEST_HEADER_ICON_HIGH,
3211 #ifdef MODEST_TOOLKIT_HILDON2
3212 HILDON_ICON_SIZE_SMALL
3214 GTK_ICON_SIZE_BUTTON
3217 gtk_widget_show (priv->priority_icon);
3218 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3219 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
3221 case TNY_HEADER_FLAG_LOW_PRIORITY:
3222 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3223 MODEST_HEADER_ICON_LOW,
3224 #ifdef MODEST_TOOLKIT_HILDON2
3225 HILDON_ICON_SIZE_SMALL
3227 GTK_ICON_SIZE_BUTTON
3230 gtk_widget_show (priv->priority_icon);
3231 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3232 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3235 gtk_widget_hide (priv->priority_icon);
3236 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3237 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3240 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3241 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3243 gtk_widget_queue_resize (priv->subject_box);
3247 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3250 ModestMsgEditWindowPrivate *priv;
3251 ModestWindowPrivate *parent_priv;
3252 gint current_format;
3254 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3256 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3257 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3259 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3260 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3262 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3264 if (current_format != file_format) {
3265 switch (file_format) {
3266 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3267 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3268 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3269 update_signature (window, priv->last_from_account, priv->last_from_account);
3270 if (parent_priv->toolbar)
3271 on_show_toolbar_button_toggled (priv->show_toolbar_button,
3272 MODEST_MSG_EDIT_WINDOW (window));
3274 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3277 response = modest_platform_run_confirmation_dialog (NULL, _("emev_nc_formatting_lost"));
3278 if (response == GTK_RESPONSE_OK) {
3279 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3280 if (parent_priv->toolbar)
3281 on_show_toolbar_button_toggled (priv->show_toolbar_button,
3282 MODEST_MSG_EDIT_WINDOW (window));
3284 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3285 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3290 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3291 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3292 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3297 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3299 #ifdef MODEST_TOOLKIT_HILDON2
3301 ModestMsgEditWindowPrivate *priv;
3302 WPTextBufferFormat oldfmt, fmt;
3303 gint old_position = 0;
3307 GdkColor *color = NULL;
3308 gboolean bold, bold_set, italic, italic_set;
3309 gboolean underline, underline_set;
3310 gboolean strikethrough, strikethrough_set;
3311 gboolean position_set;
3312 gboolean font_size_set, font_set, color_set;
3315 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3316 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3318 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3319 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3320 GTK_WINDOW(dialog), GTK_WINDOW (window));
3322 /* First we get the currently selected font information */
3323 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3325 switch (oldfmt.text_position) {
3326 case TEXT_POSITION_NORMAL:
3329 case TEXT_POSITION_SUPERSCRIPT:
3337 g_object_set (G_OBJECT (dialog),
3338 "bold", oldfmt.bold != FALSE,
3339 "bold-set", !oldfmt.cs.bold,
3340 "underline", oldfmt.underline != FALSE,
3341 "underline-set", !oldfmt.cs.underline,
3342 "italic", oldfmt.italic != FALSE,
3343 "italic-set", !oldfmt.cs.italic,
3344 "strikethrough", oldfmt.strikethrough != FALSE,
3345 "strikethrough-set", !oldfmt.cs.strikethrough,
3346 "color", &oldfmt.color,
3347 "color-set", !oldfmt.cs.color,
3348 "size", wp_font_size[oldfmt.font_size],
3349 "size-set", !oldfmt.cs.font_size,
3350 "position", old_position,
3351 "position-set", !oldfmt.cs.text_position,
3352 "family", wp_get_font_name (oldfmt.font),
3353 "family-set", !oldfmt.cs.font,
3356 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3357 GTK_WINDOW (dialog), GTK_WINDOW (window));
3358 gtk_widget_show_all (dialog);
3359 priv->font_dialog = dialog;
3360 response = gtk_dialog_run (GTK_DIALOG (dialog));
3361 priv->font_dialog = NULL;
3362 if (response == GTK_RESPONSE_OK) {
3364 g_object_get( dialog,
3366 "bold-set", &bold_set,
3367 "underline", &underline,
3368 "underline-set", &underline_set,
3370 "italic-set", &italic_set,
3371 "strikethrough", &strikethrough,
3372 "strikethrough-set", &strikethrough_set,
3374 "color-set", &color_set,
3376 "size-set", &font_size_set,
3377 "family", &font_name,
3378 "family-set", &font_set,
3379 "position", &position,
3380 "position-set", &position_set,
3385 if (response == GTK_RESPONSE_OK) {
3386 memset(&fmt, 0, sizeof(fmt));
3392 fmt.italic = italic;
3393 fmt.cs.italic = TRUE;
3395 if (underline_set) {
3396 fmt.underline = underline;
3397 fmt.cs.underline = TRUE;
3399 if (strikethrough_set) {
3400 fmt.strikethrough = strikethrough;
3401 fmt.cs.strikethrough = TRUE;
3406 ? TEXT_POSITION_NORMAL
3407 : ( ( position == 1 )
3408 ? TEXT_POSITION_SUPERSCRIPT
3409 : TEXT_POSITION_SUBSCRIPT );
3410 fmt.cs.text_position = TRUE;
3411 fmt.font_size = oldfmt.font_size;
3415 fmt.cs.color = TRUE;
3418 fmt.font = wp_get_font_index(font_name,
3423 if (font_size_set) {
3424 fmt.cs.font_size = TRUE;
3425 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3427 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3428 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3430 gtk_widget_destroy (dialog);
3432 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3437 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3439 ModestMsgEditWindowPrivate *priv;
3440 ModestWindowPrivate *parent_priv;
3441 gboolean was_rich_text, is_rich_text;
3443 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3444 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3445 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3447 was_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3449 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3451 is_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3453 if (parent_priv->toolbar && was_rich_text != is_rich_text) {
3454 on_show_toolbar_button_toggled (priv->show_toolbar_button,
3455 MODEST_MSG_EDIT_WINDOW (window));
3458 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3459 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3463 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3465 ModestMsgEditWindowPrivate *priv;
3467 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3468 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3470 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3472 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3473 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3478 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3480 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3482 priv->can_undo = can_undo;
3486 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3488 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3490 priv->can_redo = can_redo;
3494 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3496 ModestMsgEditWindowPrivate *priv;
3497 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3498 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3500 return priv->can_undo;
3504 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3506 ModestMsgEditWindowPrivate *priv;
3507 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3508 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3510 return priv->can_redo;
3515 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3518 GtkTextIter match_start, match_end;
3520 if (image_id == NULL)
3523 gtk_text_buffer_get_start_iter (buffer, &iter);
3525 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3526 GSList *tags = gtk_text_iter_get_tags (&match_start);
3528 for (node = tags; node != NULL; node = g_slist_next (node)) {
3529 GtkTextTag *tag = (GtkTextTag *) node->data;
3530 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3531 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3532 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3534 offset = gtk_text_iter_get_offset (&match_start);
3535 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3536 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3540 gtk_text_iter_forward_char (&iter);
3545 message_is_empty (ModestMsgEditWindow *window)
3547 ModestMsgEditWindowPrivate *priv = NULL;
3549 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3550 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3552 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3553 * so we can ignore markup.
3555 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3558 count = gtk_text_buffer_get_char_count (buf);
3564 msg_body_focus (GtkWidget *focus,
3565 GdkEventFocus *event,
3569 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3570 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3571 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3576 recpt_field_changed (GtkTextBuffer *buffer,
3577 ModestMsgEditWindow *editor)
3579 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3580 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3584 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3586 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3587 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3591 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3594 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3595 GtkTextBuffer *buffer;
3597 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3598 gtk_text_buffer_set_modified (buffer, modified);
3599 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3600 gtk_text_buffer_set_modified (buffer, modified);
3601 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3602 gtk_text_buffer_set_modified (buffer, modified);
3603 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3607 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3609 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3610 const char *account_name;
3611 GtkTextBuffer *buffer;
3613 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3614 if (gtk_text_buffer_get_modified (buffer))
3616 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3617 if (gtk_text_buffer_get_modified (buffer))
3619 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3620 if (gtk_text_buffer_get_modified (buffer))
3622 if (gtk_text_buffer_get_modified (priv->text_buffer))
3625 account_name = modest_selector_get_active_id (priv->from_field);
3626 if (priv->original_mailbox) {
3627 if (!account_name || strcmp (account_name, priv->original_mailbox))
3629 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3640 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3642 ModestMsgEditWindowPrivate *priv = NULL;
3643 GSList *address_list = NULL;
3644 gboolean no_to, no_cc, no_bcc;
3646 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3647 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3649 /* check if there's no recipient added */
3650 no_to = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)));
3651 no_cc = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field)));
3652 no_bcc = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field)));
3655 if (no_to && no_cc && no_bcc) {
3656 /* no recipient contents, then select contacts */
3657 modest_msg_edit_window_open_addressbook (window, NULL);
3662 g_object_ref (window);
3663 if (!no_to && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field),
3664 (add_to_addressbook) ? &address_list : NULL)) {
3665 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3666 g_object_unref (window);
3669 if (!no_cc && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field),
3670 (add_to_addressbook) ? &address_list : NULL)) {
3671 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3672 g_object_unref (window);
3675 if (!no_bcc && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field),
3676 (add_to_addressbook) ? &address_list : NULL)) {
3677 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3678 g_object_unref (window);
3682 /* Add contacts to address book */
3683 if (add_to_addressbook && address_list)
3684 modest_address_book_add_address_list (address_list);
3686 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3687 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3688 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3689 g_object_unref (window);
3696 modest_msg_edit_window_add_to_contacts (ModestMsgEditWindow *self)
3698 GSList *recipients = NULL;
3699 ModestMsgEditWindowPrivate *priv;
3700 gchar *joined, *after_remove, *to, *cc, *bcc;
3702 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3704 /* First of all check names */
3705 if (!modest_msg_edit_window_check_names (self, FALSE))
3708 if (!modest_msg_edit_window_has_pending_addresses (self))
3711 /* Don't add the from obviously */
3712 to = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->to_field));
3713 cc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->cc_field));
3714 bcc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->bcc_field));
3716 joined = modest_text_utils_join_addresses (NULL, to, cc, bcc);
3721 after_remove = modest_text_utils_remove_duplicate_addresses (joined);
3724 recipients = modest_text_utils_split_addresses_list (after_remove);
3725 g_free (after_remove);
3728 /* Offer the user to add recipients to the address book */
3729 modest_address_book_add_address_list_with_selector (recipients, (GtkWindow *) self);
3730 g_slist_foreach (recipients, (GFunc) g_free, NULL); g_slist_free (recipients);
3735 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3736 ModestMsgEditWindow *window)
3738 modest_msg_edit_window_offer_attach_file (window);
3742 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3744 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3746 return priv->clipboard_text;
3750 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3752 ModestMsgEditWindow *window)
3754 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3755 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3758 /* It could happen that the window was already closed */
3759 if (!GTK_WIDGET_VISIBLE (window))
3762 g_object_ref (window);
3763 text = gtk_clipboard_wait_for_text (selection_clipboard);
3765 if (priv->clipboard_text != NULL) {
3766 g_free (priv->clipboard_text);
3768 priv->clipboard_text = text;
3770 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3772 g_object_unref (window);
3775 static gboolean clipboard_owner_change_idle (gpointer userdata)
3777 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3778 ModestMsgEditWindowPrivate *priv;
3780 gdk_threads_enter ();
3781 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3782 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3784 priv->clipboard_owner_idle = 0;
3785 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3786 gdk_threads_leave ();
3792 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3794 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3795 if (priv->clipboard_owner_idle == 0) {
3796 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3797 clipboard_owner_change_idle,
3798 g_object_ref (window),
3804 subject_field_move_cursor (GtkEntry *entry,
3805 GtkMovementStep step,
3810 /* It could happen that the window was already closed */
3811 if (!GTK_WIDGET_VISIBLE (window))
3814 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3818 update_window_title (ModestMsgEditWindow *window)
3820 ModestMsgEditWindowPrivate *priv = NULL;
3821 const gchar *subject;
3823 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3824 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3825 if (subject == NULL || subject[0] == '\0')
3826 subject = _("mail_va_new_email");
3828 modest_window_set_title (MODEST_WINDOW (window), subject);
3834 body_insert_text (GtkTextBuffer *buffer,
3835 GtkTextIter *location,
3838 ModestMsgEditWindow *window)
3840 GtkTextIter end_iter;
3847 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3849 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3851 offset = gtk_text_iter_get_offset (&end_iter);
3852 line = gtk_text_iter_get_line (&end_iter);
3856 while (text_offset < text + len) {
3857 if (*text_offset == '\n')
3859 if (text_lines + line >= MAX_BODY_LINES) {
3860 len = text_offset - text;
3866 utf8_len = g_utf8_strlen (text, len);
3868 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3869 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3870 if (line <= MAX_BODY_LINES && offset < MAX_BODY_LENGTH)
3875 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3877 /* Prevent endless recursion */
3878 result = g_strndup (text, utf8_end - text);
3879 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3880 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3881 (gpointer) result, (gpointer) (utf8_end - text),
3883 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3887 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3888 if (priv->max_chars_banner == NULL) {
3889 #ifdef MODEST_TOOLKIT_HILDON2
3890 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3891 _CS_MAXIMUM_CHARACTERS_REACHED);
3892 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3899 subject_field_changed (GtkEditable *editable,
3900 ModestMsgEditWindow *window)
3902 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3903 update_window_title (window);
3904 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3905 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3906 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3909 subject_field_insert_text (GtkEditable *editable,
3911 gint new_text_length,
3913 ModestMsgEditWindow *window)
3915 GString *result = g_string_new ("");
3917 gint result_len = 0;
3918 const gchar *entry_text = NULL;
3921 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3922 old_length = g_utf8_strlen (entry_text, -1);
3924 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3925 gunichar c = g_utf8_get_char_validated (current, 8);
3926 /* Invalid unichar, stop */
3932 result = g_string_append_unichar (result, c);
3936 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3937 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3940 /* Prevent endless recursion */
3941 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3942 g_signal_emit_by_name (editable, "insert-text",
3943 (gpointer) result->str, (gpointer) result->len,
3944 (gpointer) position, (gpointer) window);
3945 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3949 if (result_len + old_length > 1000) {
3950 modest_platform_system_banner (GTK_WIDGET (window), NULL,
3951 _CS_MAXIMUM_CHARACTERS_REACHED);
3953 g_string_free (result, TRUE);
3957 modest_msg_edit_window_toggle_isearch_toolbar (ModestMsgEditWindow *window,
3960 ModestMsgEditWindowPrivate *priv = NULL;
3962 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3963 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3965 gtk_widget_set_no_show_all (priv->isearch_toolbar, FALSE);
3968 gtk_widget_show_all (priv->isearch_toolbar);
3969 modest_isearch_toolbar_highlight_entry (MODEST_ISEARCH_TOOLBAR (priv->isearch_toolbar), TRUE);
3971 gtk_widget_hide_all (priv->isearch_toolbar);
3972 gtk_widget_grab_focus (priv->msg_body);
3977 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3979 GtkTextIter *match_start,
3980 GtkTextIter *match_end)
3982 GtkTextIter end_iter;
3983 gchar *str_casefold;
3986 gchar *range_casefold;
3989 gboolean result = FALSE;
3996 gtk_text_iter_forward_to_end (&end_iter);
3998 str_casefold = g_utf8_casefold (str, -1);
3999 str_chars_n = strlen (str);
4001 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
4002 range_casefold = g_utf8_casefold (range_text, -1);
4003 range_chars_n = strlen (range_casefold);
4005 if (range_chars_n < str_chars_n) {
4006 g_free (str_casefold);
4007 g_free (range_text);
4008 g_free (range_casefold);
4012 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
4013 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
4014 if (!g_utf8_collate (range_subtext, str_casefold)) {
4015 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
4017 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
4018 match_start, match_end, NULL)) {
4019 g_debug ("Matched string with collate, but not matched in model");
4021 g_free (found_text);
4023 g_free (range_subtext);
4027 g_free (str_casefold);
4028 g_free (range_text);
4029 g_free (range_casefold);
4036 modest_msg_edit_window_isearch_toolbar_search (GtkWidget *widget,
4037 ModestMsgEditWindow *window)
4039 const gchar *current_search = NULL;
4040 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4042 GtkTextIter selection_start, selection_end;
4043 GtkTextIter match_start, match_end;
4044 gboolean continue_search = FALSE;
4046 if (message_is_empty (window)) {
4047 g_free (priv->last_search);
4048 priv->last_search = NULL;
4049 modest_platform_system_banner (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
4053 current_search = modest_isearch_toolbar_get_search (MODEST_ISEARCH_TOOLBAR (widget));
4054 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
4055 g_free (priv->last_search);
4056 priv->last_search = NULL;
4057 /* Information banner about empty search */
4058 modest_platform_system_banner (NULL, NULL, _CS_FIND_REP_ENTER_TEXT);
4062 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
4063 continue_search = TRUE;
4065 g_free (priv->last_search);
4066 priv->last_search = g_strdup (current_search);
4069 if (continue_search) {
4070 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
4071 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
4072 &match_start, &match_end);
4074 modest_platform_system_banner (NULL, NULL, _HL_IB_FIND_COMPLETE);
4076 GtkTextIter buffer_start;
4077 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
4078 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
4079 &match_start, &match_end);
4081 modest_platform_system_banner (NULL, NULL, _HL_IB_FIND_NO_MATCHES);
4084 /* Mark as selected the string found in search */
4086 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
4087 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
4088 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
4090 g_free (priv->last_search);
4091 priv->last_search = NULL;
4096 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
4098 ModestMsgEditWindowPrivate *priv;
4100 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
4105 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
4108 ModestMsgEditWindowPrivate *priv;
4110 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
4115 modest_msg_edit_window_isearch_toolbar_close (GtkWidget *widget,
4116 ModestMsgEditWindow *window)
4118 modest_msg_edit_window_toggle_isearch_toolbar (window, FALSE);
4122 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
4125 ModestMsgEditWindowPrivate *priv;
4126 TnyHeader *header = NULL;
4128 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4129 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
4131 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4133 if (priv->draft_msg != NULL) {
4134 g_object_unref (priv->draft_msg);
4137 if (draft != NULL) {
4138 g_object_ref (draft);
4139 header = tny_msg_get_header (draft);
4140 if (priv->msg_uid) {
4141 g_free (priv->msg_uid);
4142 priv->msg_uid = NULL;
4144 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
4147 priv->draft_msg = draft;
4151 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
4152 GtkTextIter *start, GtkTextIter *end,
4155 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
4156 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
4159 if (tag == NULL) return;
4160 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
4161 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
4162 replace_with_images (window, priv->images);
4167 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
4170 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4172 g_return_if_fail (TNY_IS_MIME_PART (part));
4173 tny_list_prepend (priv->attachments, (GObject *) part);
4174 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
4175 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
4176 gtk_widget_show_all (priv->attachments_caption);
4177 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
4181 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
4183 ModestMsgEditWindowPrivate *priv;
4185 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
4186 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4188 return priv->msg_uid;
4192 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
4193 ModestMsgEditWindowWidgetType widget_type)
4195 ModestMsgEditWindowPrivate *priv;
4197 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
4198 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
4200 switch (widget_type) {
4201 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
4202 return priv->msg_body;
4204 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
4205 return priv->to_field;
4207 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
4208 return priv->cc_field;
4210 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
4211 return priv->bcc_field;
4213 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
4214 return priv->subject_field;
4216 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
4217 return priv->attachments_view;
4225 remove_tags (WPTextBuffer *buffer)
4227 GtkTextIter start, end;
4229 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
4230 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
4232 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
4236 on_account_removed (TnyAccountStore *account_store,
4237 TnyAccount *account,
4240 /* Do nothing if it's a store account, because we use the
4241 transport to send the messages */
4242 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
4243 const gchar *parent_acc = NULL;
4244 const gchar *our_acc = NULL;
4246 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
4247 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
4248 /* Close this window if I'm showing a message of the removed account */
4249 if (strcmp (parent_acc, our_acc) == 0)
4250 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
4255 update_signature (ModestMsgEditWindow *self,
4256 const gchar *old_account,
4257 const gchar *new_account)
4259 ModestMsgEditWindowPrivate *priv;
4260 gboolean has_old_signature, has_new_signature;
4262 ModestAccountMgr *mgr;
4265 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4267 gtk_text_buffer_begin_user_action (priv->text_buffer);
4269 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
4270 mgr = modest_runtime_get_account_mgr ();
4274 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
4275 if (has_old_signature) {
4276 GtkTextIter match_start, match_end;
4278 MODEST_TEXT_UTILS_SIGNATURE_MARKER as it
4279 seems that the search has some problems
4280 with the blank space at the end */
4281 if (gtk_text_iter_forward_search (&iter, "--",
4282 GTK_TEXT_SEARCH_TEXT_ONLY,
4283 &match_start, NULL, NULL)) {
4284 gtk_text_buffer_get_end_iter (priv->text_buffer ,&match_end);
4285 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
4287 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
4288 &match_start, &match_end, NULL)) {
4292 gtk_text_buffer_get_end_iter (priv->text_buffer, &iter);
4297 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
4298 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
4299 if (has_new_signature) {
4302 gchar *full_signature = g_strconcat ((gtk_text_iter_starts_line (&iter)) ? "" : "\n",
4303 MODEST_TEXT_UTILS_SIGNATURE_MARKER, "\n",
4305 is_rich = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
4307 WPTextBufferFormat *fmt;
4308 GdkColor style_color;
4309 if (!gtk_style_lookup_color (GTK_WIDGET (self)->style, "SecondaryTextColor", &style_color)) {
4310 gdk_color_parse ("grey", &style_color);
4312 fmt = g_new0 (WPTextBufferFormat, 1);
4313 fmt->color = style_color;
4314 fmt->cs.color = 0x1;
4315 wp_text_buffer_insert_with_attribute (WP_TEXT_BUFFER (priv->text_buffer), &iter,
4319 g_free (full_signature);
4321 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4325 gtk_text_buffer_end_user_action (priv->text_buffer);
4328 static void update_branding (ModestMsgEditWindow *self,
4329 const gchar *new_account)
4331 ModestMsgEditWindowPrivate *priv;
4332 ModestAccountMgr *mgr;
4333 const GdkPixbuf *new_icon = NULL;
4334 gchar *new_label = NULL;
4335 gboolean show = FALSE;
4337 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4339 mgr = modest_runtime_get_account_mgr ();
4341 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4343 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4344 gtk_widget_show (priv->brand_icon);
4347 gtk_widget_hide (priv->brand_icon);
4350 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4351 gtk_widget_show (priv->brand_label);
4355 gtk_widget_hide (priv->brand_label);
4359 gtk_widget_show (priv->brand_container);
4361 gtk_widget_hide (priv->brand_container);
4365 from_field_changed (GtkWidget *button,
4366 ModestMsgEditWindow *self)
4368 ModestMsgEditWindowPrivate *priv;
4369 gchar *old_account, *new_account;
4371 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4373 old_account = priv->last_from_account;
4374 new_account = modest_selector_get_active_id (priv->from_field);
4377 g_warning ("%s, could not get the new account", __FUNCTION__);
4381 /* If the From is the same do nothing */
4382 if (old_account && new_account && !strcmp (old_account, new_account))
4385 priv->last_from_account = new_account;
4387 update_signature (self, old_account, new_account);
4388 update_branding (self, new_account);
4392 typedef struct _MessageSettingsHelper {
4393 ModestMsgEditWindow *window;
4394 GSList *priority_group;
4395 GSList *format_group;
4396 GtkToggleButton *current_priority;
4397 GtkToggleButton *current_format;
4398 } MessageSettingsHelper;
4401 on_priority_toggle (GtkToggleButton *button,
4402 MessageSettingsHelper *helper)
4405 ModestMsgEditWindowPrivate *priv;
4407 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4408 if (gtk_toggle_button_get_active (button)) {
4410 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4411 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4412 if ((node_button != button) &&
4413 gtk_toggle_button_get_active (node_button)) {
4414 gtk_toggle_button_set_active (node_button, FALSE);
4417 helper->current_priority = button;
4419 gboolean found = FALSE;
4420 /* If no one is active, activate it again */
4421 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4422 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4423 if (gtk_toggle_button_get_active (node_button)) {
4429 gtk_toggle_button_set_active (button, TRUE);
4435 on_format_toggle (GtkToggleButton *button,
4436 MessageSettingsHelper *helper)
4439 ModestMsgEditWindowPrivate *priv;
4441 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4442 if (gtk_toggle_button_get_active (button)) {
4444 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4445 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4446 if ((node_button != button) &&
4447 gtk_toggle_button_get_active (node_button)) {
4448 gtk_toggle_button_set_active (node_button, FALSE);
4451 helper->current_format = button;
4453 gboolean found = FALSE;
4454 /* If no one is active, activate it again */
4455 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4456 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4457 if (gtk_toggle_button_get_active (node_button)) {
4463 gtk_toggle_button_set_active (button, TRUE);
4470 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4475 GtkWidget *priority_hbox;
4476 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4477 GtkWidget *captioned;
4478 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4479 GtkWidget *format_hbox;
4480 GtkWidget *html_toggle, *text_toggle;
4481 ModestMsgEditWindowPrivate *priv;
4482 MessageSettingsHelper helper = {0,};
4484 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4485 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4486 helper.window = window;
4487 helper.priority_group = NULL;
4488 helper.format_group = NULL;
4490 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4491 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4493 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4494 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4495 _HL_DONE, GTK_RESPONSE_ACCEPT, NULL);
4496 vbox = gtk_vbox_new (FALSE, 0);
4497 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4498 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4499 gtk_container_add (GTK_CONTAINER (align), vbox);
4500 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4501 gtk_widget_show (align);
4502 gtk_widget_show (vbox);
4504 /* Priority toggles */
4505 priority_hbox = gtk_hbox_new (TRUE, 0);
4506 #ifdef MODEST_TOOLKIT_HILDON2
4507 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4509 high_toggle = gtk_toggle_button_new ();
4511 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4512 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4513 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4514 #ifdef MODEST_TOOLKIT_HILDON2
4515 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4517 medium_toggle = gtk_toggle_button_new ();
4519 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4520 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4521 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4522 #ifdef MODEST_TOOLKIT_HILDON2
4523 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4525 low_toggle = gtk_toggle_button_new ();
4527 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4528 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4529 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4530 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4531 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4532 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4533 gtk_widget_show_all (priority_hbox);
4534 captioned = modest_toolkit_utils_create_captioned (title_sizegroup, value_sizegroup,
4535 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4536 gtk_widget_show (captioned);
4537 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4539 /* format toggles */
4540 format_hbox = gtk_hbox_new (TRUE, 0);
4541 #ifdef MODEST_TOOLKIT_HILDON2
4542 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4544 html_toggle = gtk_toggle_button_new ();
4546 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4547 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4548 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4549 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4550 #ifdef MODEST_TOOLKIT_HILDON2
4551 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4553 text_toggle = gtk_toggle_button_new ();
4555 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4556 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4557 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4558 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4559 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4560 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4561 gtk_widget_show_all (format_hbox);
4562 gtk_widget_show (format_hbox);
4563 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4566 g_object_unref (title_sizegroup);
4567 g_object_unref (value_sizegroup);
4569 /* Set current values */
4570 switch (priv->priority_flags) {
4571 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4572 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4573 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4575 case TNY_HEADER_FLAG_LOW_PRIORITY:
4576 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4577 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4580 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4581 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4585 switch (modest_msg_edit_window_get_format (window)) {
4586 case MODEST_MSG_EDIT_FORMAT_TEXT:
4587 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4588 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4590 case MODEST_MSG_EDIT_FORMAT_HTML:
4592 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4593 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4597 /* Signal connects */
4598 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4599 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4600 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4601 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4602 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4604 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4605 GTK_WINDOW (dialog), GTK_WINDOW (window));
4607 /* Save settings if the user clicked on done */
4608 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4609 TnyHeaderFlags flags;
4610 ModestMsgEditFormat old_format, new_format;
4612 /* Set priority flags */
4613 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4614 if (priv->priority_flags != flags)
4615 modest_msg_edit_window_set_priority_flags (window, flags);
4617 /* Set edit format */
4618 old_format = modest_msg_edit_window_get_format (window);
4619 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4620 if (old_format != new_format) {
4621 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4622 modest_msg_edit_window_set_file_format (window, file_format);
4626 gtk_widget_destroy (dialog);
4627 g_slist_free (helper.priority_group);
4631 on_message_settings (GtkAction *action,
4632 ModestMsgEditWindow *window)
4634 modest_msg_edit_window_show_msg_settings_dialog (window);
4638 on_show_toolbar_button_toggled (GtkWidget *button,
4639 ModestMsgEditWindow *window)
4641 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4643 modest_msg_edit_window_show_toolbar (MODEST_WINDOW (window),
4644 modest_togglable_get_active (button));
4648 on_cc_button_toggled (GtkWidget *button,
4649 ModestMsgEditWindow *window)
4651 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4653 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4654 modest_togglable_get_active (button));
4658 on_bcc_button_toggled (GtkWidget *button,
4659 ModestMsgEditWindow *window)
4661 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4663 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4664 modest_togglable_get_active (button));
4668 setup_menu (ModestMsgEditWindow *self)
4670 ModestMsgEditWindowPrivate *priv = NULL;
4672 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4674 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4676 /* Settings menu buttons */
4677 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4678 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_check_names),
4680 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_viewer_addtocontacts"), NULL,
4681 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_add_to_contacts),
4682 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_add_to_contacts));
4683 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4684 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_undo),
4685 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4687 priv->cc_button = modest_toolkit_factory_create_check_menu (modest_runtime_get_toolkit_factory (),
4688 _("mcen_me_editor_showcc"));
4689 modest_togglable_set_active (priv->cc_button,
4691 modest_window_add_item_to_menu (MODEST_WINDOW (self), priv->cc_button, NULL);
4692 gtk_widget_show (priv->cc_button);
4693 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4694 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4696 priv->bcc_button = modest_toolkit_factory_create_check_menu (modest_runtime_get_toolkit_factory (),
4697 _("mcen_me_editor_showbcc"));
4698 gtk_widget_show (priv->bcc_button);
4699 modest_togglable_set_active (priv->bcc_button,
4701 modest_window_add_item_to_menu (MODEST_WINDOW (self), priv->bcc_button,
4703 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4704 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4706 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4707 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4708 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4709 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4710 MODEST_WINDOW_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4712 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4713 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4714 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4715 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_message_settings"), NULL,
4716 MODEST_WINDOW_MENU_CALLBACK (on_message_settings),
4718 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4719 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4722 priv->show_toolbar_button = modest_toolkit_factory_create_check_menu (modest_runtime_get_toolkit_factory (),
4723 _("mcen_bd_show_toolbar"));
4724 modest_togglable_set_active (priv->show_toolbar_button,
4726 modest_window_add_item_to_menu (MODEST_WINDOW (self), priv->show_toolbar_button,
4727 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_show_toolbar));
4728 gtk_widget_show (priv->show_toolbar_button);
4729 g_signal_connect (G_OBJECT (priv->show_toolbar_button), "toggled",
4730 G_CALLBACK (on_show_toolbar_button_toggled), (gpointer) self);
4735 emit_open_addressbook (GtkButton *button,
4736 ModestRecptEditor *editor)
4738 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4742 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4743 const gchar *label, GtkWidget *control)
4745 GtkWidget *abook_button;
4748 GtkWidget *label_widget;
4750 box = gtk_hbox_new (FALSE, 0);
4752 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4753 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4755 #ifdef MODEST_TOOLKIT_HILDON2
4756 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4758 abook_button = gtk_button_new ();
4760 label_widget = gtk_label_new (label);
4761 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4762 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4764 gtk_container_add (GTK_CONTAINER (align), abook_button);
4765 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4766 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4767 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4768 if (title_size_group)
4769 gtk_size_group_add_widget (title_size_group, label_widget);
4770 if (value_size_group)
4771 gtk_size_group_add_widget (value_size_group, control);
4773 g_signal_connect (G_OBJECT (abook_button), "clicked",
4774 G_CALLBACK (emit_open_addressbook), control);
4780 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4782 ModestMsgEditWindowPrivate *priv = NULL;
4784 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4786 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4787 priv->max_chars_banner = NULL;
4791 has_pending_addresses (ModestRecptEditor *recpt_editor)
4793 const gchar *recipients = NULL;
4794 GSList *start_indexes = NULL, *end_indexes = NULL;
4795 GSList *current_start, *current_end;
4796 GtkTextBuffer *buffer;
4797 gint offset_delta = 0;
4799 gboolean has_recipients_to_add = FALSE;
4801 recipients = modest_recpt_editor_get_recipients (recpt_editor);
4802 last_length = g_utf8_strlen (recipients, -1);
4803 modest_text_utils_get_addresses_indexes (recipients, &start_indexes, &end_indexes);
4808 current_start = start_indexes;
4809 current_end = end_indexes;
4810 buffer = modest_recpt_editor_get_buffer (recpt_editor);
4812 while (current_start && !has_recipients_to_add) {
4814 gchar *start_ptr, *end_ptr;
4815 gint start_pos, end_pos;
4817 start_pos = (*((gint*) current_start->data)) + offset_delta;
4818 end_pos = (*((gint*) current_end->data)) + offset_delta;
4820 start_ptr = g_utf8_offset_to_pointer (recipients, start_pos);
4821 end_ptr = g_utf8_offset_to_pointer (recipients, end_pos);
4823 address = g_strstrip (g_strndup (start_ptr, end_ptr - start_ptr));
4825 if (modest_text_utils_validate_recipient (address, NULL)) {
4826 if (!modest_address_book_has_address (address)) {
4827 has_recipients_to_add = TRUE;
4830 current_start = g_slist_next (current_start);
4831 current_end = g_slist_next (current_end);
4833 return has_recipients_to_add;
4837 modest_msg_edit_window_has_pending_addresses (ModestMsgEditWindow *self)
4839 ModestMsgEditWindowPrivate *priv = NULL;
4841 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self), FALSE);
4843 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4845 if (!has_pending_addresses ((ModestRecptEditor *) priv->to_field) &&
4846 !has_pending_addresses ((ModestRecptEditor *) priv->cc_field) &&
4847 !has_pending_addresses ((ModestRecptEditor *) priv->bcc_field))