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;
350 TnyList *custom_header_pairs;
353 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
354 MODEST_TYPE_MSG_EDIT_WINDOW, \
355 ModestMsgEditWindowPrivate))
357 static ModestWindowParentClass *parent_class = NULL;
359 /* uncomment the following if you have defined any signals */
360 /* static guint signals[LAST_SIGNAL] = {0}; */
363 modest_msg_edit_window_get_type (void)
365 static GType my_type = 0;
367 static const GTypeInfo my_info = {
368 sizeof(ModestMsgEditWindowClass),
369 NULL, /* base init */
370 NULL, /* base finalize */
371 (GClassInitFunc) modest_msg_edit_window_class_init,
372 NULL, /* class finalize */
373 NULL, /* class data */
374 sizeof(ModestMsgEditWindow),
376 (GInstanceInitFunc) modest_msg_edit_window_init,
379 my_type = g_type_register_static (
380 #ifdef MODEST_TOOLKIT_HILDON2
381 MODEST_TYPE_HILDON2_WINDOW,
383 MODEST_TYPE_SHELL_WINDOW,
385 "ModestMsgEditWindow",
393 save_state (ModestWindow *self)
395 modest_widget_memory_save (modest_runtime_get_conf(),
396 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
401 restore_settings (ModestMsgEditWindow *self)
403 ModestConf *conf = NULL;
405 conf = modest_runtime_get_conf ();
407 /* Dim at start clipboard actions */
408 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
413 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
415 GObjectClass *gobject_class;
416 ModestWindowClass *modest_window_class;
417 gobject_class = (GObjectClass*) klass;
418 modest_window_class = (ModestWindowClass*) klass;
420 parent_class = g_type_class_peek_parent (klass);
421 gobject_class->finalize = modest_msg_edit_window_finalize;
423 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
424 modest_window_class->save_state_func = save_state;
425 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
427 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
431 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
433 ModestMsgEditWindowPrivate *priv;
434 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
436 priv->msg_body = NULL;
437 priv->from_field = NULL;
438 priv->to_field = NULL;
439 priv->cc_field = NULL;
440 priv->bcc_field = NULL;
441 priv->subject_field = NULL;
442 priv->attachments = TNY_LIST (tny_simple_list_new ());
443 priv->images = TNY_LIST (tny_simple_list_new ());
444 priv->images_size = 0;
445 priv->images_count = 0;
448 priv->cc_caption = NULL;
449 priv->bcc_caption = NULL;
450 priv->update_caption_visibility = FALSE;
452 priv->priority_flags = 0;
454 priv->isearch_toolbar = NULL;
455 priv->last_search = NULL;
457 priv->draft_msg = NULL;
458 priv->outbox_msg = NULL;
459 priv->msg_uid = NULL;
461 priv->can_undo = FALSE;
462 priv->can_redo = FALSE;
463 priv->clipboard_change_handler_id = 0;
464 priv->default_clipboard_change_handler_id = 0;
465 priv->account_removed_handler_id = 0;
466 priv->clipboard_owner_idle = 0;
467 priv->clipboard_text = NULL;
470 priv->scroll_drag_timeout_id = 0;
471 priv->correct_scroll_idle = 0;
472 priv->last_upper = 0.0;
474 priv->font_dialog = NULL;
475 priv->app_menu = NULL;
477 priv->references = NULL;
478 priv->in_reply_to = NULL;
479 priv->max_chars_banner = NULL;
480 priv->custom_header_pairs = TNY_LIST (tny_simple_list_new ());
482 if (!is_wp_text_buffer_started) {
483 is_wp_text_buffer_started = TRUE;
484 wp_text_buffer_library_init ();
488 #ifdef MODEST_TOOLKIT_HILDON2
489 hildon_program_add_window (hildon_program_get_instance(),
495 multimailbox_get_default_mailbox (const gchar *account_name)
497 gchar *transport_account;
498 gchar *result = NULL;
500 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
502 TNY_ACCOUNT_TYPE_TRANSPORT);
503 if (transport_account) {
505 ModestProtocolRegistry *registry;
507 registry = modest_runtime_get_protocol_registry ();
509 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
510 MODEST_ACCOUNT_PROTO, TRUE);
512 ModestProtocol *protocol =
513 modest_protocol_registry_get_protocol_by_name (registry,
514 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
516 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
517 ModestPairList *pair_list;
519 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
522 ModestPair *pair = (ModestPair *) pair_list->data;
523 result = g_strdup ((const gchar *) pair->first);
524 modest_pair_list_free (pair_list);
535 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
537 static ModestPairList*
538 get_transports (void)
540 GSList *transports = NULL;
542 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
543 GSList *accounts = modest_account_mgr_account_names (account_mgr,
544 TRUE /* only enabled accounts. */);
546 GSList *cursor = accounts;
548 gchar *account_name = cursor->data;
551 gchar *transport_account;
552 gboolean multi_mailbox = FALSE;
553 ModestProtocol *protocol = NULL;
555 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
557 transport_account = modest_account_mgr_get_server_account_name
558 (modest_runtime_get_account_mgr (),
560 TNY_ACCOUNT_TYPE_TRANSPORT);
561 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
562 ModestPairList *pair_list;
563 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
566 transports = g_slist_concat (transports, pair_list);
567 multi_mailbox = TRUE;
572 if (!multi_mailbox) {
573 gchar *from_string = NULL;
575 from_string = modest_account_mgr_get_from_string (account_mgr,
577 if (from_string && account_name) {
578 gchar *name = account_name;
579 ModestPair *pair = modest_pair_new ((gpointer) name,
580 (gpointer) from_string , TRUE);
581 transports = g_slist_prepend (transports, pair);
586 cursor = cursor->next;
588 g_slist_free (accounts); /* only free the accounts, not the elements,
589 * because they are used in the pairlist */
593 static void window_focus (GtkWindow *window,
597 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
601 scroll_drag_timeout (gpointer userdata)
603 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
604 ModestMsgEditWindowPrivate *priv;
606 /* It could happen that the window was already closed */
607 if (!GTK_WIDGET_VISIBLE (win))
610 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
612 correct_scroll_without_drag_check (win, TRUE);
614 priv->scroll_drag_timeout_id = 0;
620 correct_scroll_without_drag_check_idle (gpointer userdata)
622 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
623 ModestMsgEditWindowPrivate *priv;
625 GdkRectangle rectangle;
626 gint offset_min, offset_max;
630 /* It could happen that the window was already closed */
631 if (!GTK_WIDGET_VISIBLE (w))
634 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
636 insert = gtk_text_buffer_get_insert (priv->text_buffer);
637 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
639 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
640 offset_min = priv->msg_body->allocation.y + rectangle.y;
641 offset_max = offset_min + rectangle.height;
643 vadj = modest_scrollable_get_vadjustment (MODEST_SCROLLABLE (priv->scrollable));
644 offset_min = MAX (offset_min - 48, 0);
645 offset_max = MIN (offset_max + 48, vadj->upper);
647 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
649 priv->correct_scroll_idle = 0;
654 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
656 ModestMsgEditWindowPrivate *priv;
658 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
660 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
663 if (priv->correct_scroll_idle > 0) {
667 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
668 (GSourceFunc) correct_scroll_without_drag_check_idle,
674 correct_scroll (ModestMsgEditWindow *w)
676 ModestMsgEditWindowPrivate *priv;
678 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
679 if (gtk_grab_get_current () == priv->msg_body) {
680 if (priv->scroll_drag_timeout_id == 0) {
681 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
683 (GSourceFunc) scroll_drag_timeout,
690 correct_scroll_without_drag_check (w, TRUE);
694 text_buffer_end_user_action (GtkTextBuffer *buffer,
695 ModestMsgEditWindow *userdata)
698 correct_scroll (userdata);
702 text_buffer_mark_set (GtkTextBuffer *buffer,
705 ModestMsgEditWindow *userdata)
707 gtk_text_buffer_begin_user_action (buffer);
708 gtk_text_buffer_end_user_action (buffer);
712 cut_clipboard_check (GtkTextView *text_view,
715 GtkTextBuffer *buffer;
717 buffer = gtk_text_view_get_buffer (text_view);
718 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
719 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
724 copy_clipboard_check (GtkTextView *text_view,
727 GtkTextBuffer *buffer;
729 buffer = gtk_text_view_get_buffer (text_view);
730 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
731 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
736 attachment_deleted (ModestAttachmentsView *attachments_view,
739 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
744 body_size_request (GtkWidget *body,
748 /* Make sure the body always get at least 70 pixels */
749 if (req->height < 70)
754 connect_signals (ModestMsgEditWindow *obj)
756 ModestMsgEditWindowPrivate *priv;
758 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
760 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
761 G_CALLBACK (text_buffer_refresh_attributes), obj);
762 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
763 G_CALLBACK (text_buffer_can_undo), obj);
764 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
765 G_CALLBACK (text_buffer_can_redo), obj);
766 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
767 G_CALLBACK (body_changed), obj);
768 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
769 G_CALLBACK (body_insert_text), obj);
770 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
771 G_CALLBACK (body_changed), obj);
772 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
773 G_CALLBACK (text_buffer_end_user_action), obj);
774 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
775 G_CALLBACK (text_buffer_mark_set), obj);
776 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
777 G_CALLBACK (text_buffer_apply_tag), obj);
778 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
779 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
780 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
781 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
782 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
783 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
785 g_signal_connect (G_OBJECT (priv->send_button), "clicked",
786 G_CALLBACK (modest_ui_actions_on_send), obj);
788 if (GTK_IS_COMBO_BOX (priv->from_field)) {
789 g_signal_connect (G_OBJECT (priv->from_field), "changed",
790 G_CALLBACK (from_field_changed), obj);
792 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
793 G_CALLBACK (from_field_changed), obj);
796 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
797 G_CALLBACK (msg_body_focus), obj);
798 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
799 G_CALLBACK (msg_body_focus), obj);
800 g_signal_connect (G_OBJECT (priv->msg_body), "size-request",
801 G_CALLBACK (body_size_request), obj);
802 if (GTK_IS_WINDOW (obj)) {
803 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
805 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
806 "changed", G_CALLBACK (recpt_field_changed), obj);
807 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
808 "changed", G_CALLBACK (recpt_field_changed), obj);
809 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
810 "changed", G_CALLBACK (recpt_field_changed), obj);
811 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
812 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
813 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
815 g_signal_connect (G_OBJECT (priv->isearch_toolbar), "isearch-search",
816 G_CALLBACK (modest_msg_edit_window_isearch_toolbar_search), obj);
817 g_signal_connect (G_OBJECT (priv->isearch_toolbar), "isearch-close",
818 G_CALLBACK (modest_msg_edit_window_isearch_toolbar_close), obj);
820 priv->clipboard_change_handler_id =
821 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
822 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
823 priv->default_clipboard_change_handler_id =
824 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
825 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
827 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
828 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
829 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
833 init_wp_text_view_style ()
835 static gboolean initialized = FALSE;
838 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
844 init_window (ModestMsgEditWindow *obj)
846 GtkWidget *to_caption, *subject_caption;
847 GtkWidget *main_vbox;
848 ModestMsgEditWindowPrivate *priv;
849 GtkActionGroup *action_group;
850 ModestWindowPrivate *parent_priv;
851 GError *error = NULL;
853 GtkSizeGroup *title_size_group;
854 GtkSizeGroup *value_size_group;
855 GtkWidget *window_box;
856 GtkWidget *window_align;
857 #if (GTK_MINOR_VERSION >= 10)
858 GdkAtom deserialize_type;
860 GtkWidget *from_send_hbox;
861 GtkWidget *send_icon;
862 GtkWidget *attachments_label;
863 GtkWidget *branding_box;
864 GtkWidget *from_caption;
866 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
867 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
869 parent_priv->ui_manager = gtk_ui_manager_new();
870 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
871 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
873 /* Add common actions */
874 gtk_action_group_add_actions (action_group,
875 modest_msg_edit_action_entries,
876 G_N_ELEMENTS (modest_msg_edit_action_entries),
878 gtk_action_group_add_actions (action_group,
879 hildon2_msg_edit_action_entries,
880 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
882 gtk_action_group_add_toggle_actions (action_group,
883 modest_msg_edit_toggle_action_entries,
884 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
886 gtk_action_group_add_radio_actions (action_group,
887 modest_msg_edit_alignment_radio_action_entries,
888 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
890 G_CALLBACK (modest_ui_actions_on_change_justify),
892 gtk_action_group_add_radio_actions (action_group,
893 modest_msg_edit_priority_action_entries,
894 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
896 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
898 gtk_action_group_add_radio_actions (action_group,
899 modest_msg_edit_file_format_action_entries,
900 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
901 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
902 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
904 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
905 g_object_unref (action_group);
907 /* Load the UI definition */
908 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
911 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
912 g_clear_error (&error);
915 parent_priv->menubar = NULL;
917 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
918 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
920 /* Note: This ModestPairList* must exist for as long as the picker
921 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
922 * so it can't know how to manage its memory. */
923 priv->from_field = modest_toolkit_factory_create_selector (modest_runtime_get_toolkit_factory (),
925 modest_selector_set_value_max_chars (priv->from_field, MAX_FROM_VALUE);
926 if (GTK_IS_COMBO_BOX (priv->from_field)) {
927 from_caption = modest_toolkit_utils_create_captioned (title_size_group, NULL,
928 _("mail_va_from"), FALSE,
930 gtk_widget_show (from_caption);
932 #ifdef MODEST_TOOLKIT_HILDON2
933 modest_toolkit_utils_set_hbutton_layout (title_size_group, NULL,
934 _("mail_va_from"), priv->from_field);
935 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
936 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
937 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
938 from_caption = priv->from_field;
942 priv->to_field = modest_recpt_editor_new ();
943 priv->cc_field = modest_recpt_editor_new ();
944 priv->bcc_field = modest_recpt_editor_new ();
945 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
946 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
947 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
948 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
949 priv->priority_icon = gtk_image_new ();
950 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
951 priv->subject_field = modest_toolkit_factory_create_entry (modest_runtime_get_toolkit_factory ());
952 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
953 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
954 modest_entry_set_hint (priv->subject_field, _("mail_va_no_subject"));
956 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
957 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
959 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
960 priv->attachments_view = modest_attachments_view_new (NULL);
961 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
962 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
964 priv->header_box = gtk_vbox_new (FALSE, 0);
966 to_caption = _create_addressbook_box
967 (title_size_group, value_size_group,
968 _("mail_va_to"), priv->to_field);
969 priv->cc_caption = _create_addressbook_box
970 (title_size_group, value_size_group,
971 _("mail_va_cc"), priv->cc_field);
972 priv->bcc_caption = _create_addressbook_box
973 (title_size_group, value_size_group,
974 _("mail_va_hotfix1"), priv->bcc_field);
975 subject_caption = modest_toolkit_utils_create_captioned (title_size_group, value_size_group,
976 _("mail_va_subject"), FALSE, priv->subject_box);
977 priv->attachments_caption = modest_toolkit_utils_create_captioned_with_size_type (NULL, NULL,
978 _("mail_va_attachment"),
980 priv->attachments_view,
981 #ifdef MODEST_TOOLKIT_HILDON2
982 HILDON_SIZE_AUTO_WIDTH |
983 HILDON_SIZE_AUTO_HEIGHT
988 attachments_label = modest_toolkit_utils_captioned_get_label_widget (priv->attachments_caption);
990 hildon_gtk_widget_set_theme_size (attachments_label, HILDON_SIZE_AUTO_HEIGHT);
994 #ifdef MODEST_TOOLKIT_HILDON2
995 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
996 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
998 priv->send_button = gtk_button_new ();
999 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, GTK_ICON_SIZE_BUTTON);
1001 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
1002 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 148, -1);
1004 g_object_unref (title_size_group);
1005 g_object_unref (value_size_group);
1007 priv->brand_icon = gtk_image_new ();
1008 gtk_misc_set_alignment (GTK_MISC (priv->brand_icon), 0.5, 0.5);
1009 priv->brand_label = gtk_label_new (NULL);
1010 #ifdef MODEST_TOOLKIT_HILDON2
1011 hildon_helper_set_logical_font (priv->brand_label, "SmallSystemFont");
1013 gtk_misc_set_alignment (GTK_MISC (priv->brand_label), 0.0, 0.5);
1014 gtk_widget_set_no_show_all (priv->brand_icon, TRUE);
1015 gtk_widget_set_no_show_all (priv->brand_label, TRUE);
1017 from_send_hbox = gtk_hbox_new (FALSE, 0);
1018 gtk_box_pack_start (GTK_BOX (from_send_hbox), from_caption, TRUE, TRUE, 0);
1019 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
1021 branding_box = gtk_hbox_new (FALSE, MODEST_MARGIN_DEFAULT);
1022 gtk_widget_show (branding_box);
1023 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_label, FALSE, FALSE, 0);
1024 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_icon, FALSE, FALSE, 0);
1026 priv->brand_container = gtk_alignment_new (0.0, 0.5, 0.0, 1.0);
1027 gtk_alignment_set_padding (GTK_ALIGNMENT (priv->brand_container), 0, 0, MODEST_MARGIN_DOUBLE, 0);
1028 gtk_container_add (GTK_CONTAINER (priv->brand_container), branding_box);
1029 gtk_widget_set_no_show_all (priv->brand_container, TRUE);
1032 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
1033 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
1034 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
1035 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
1036 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
1037 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
1038 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->brand_container, FALSE, FALSE, 0);
1039 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
1041 init_wp_text_view_style ();
1043 priv->msg_body = modest_wp_text_view_new ();
1046 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
1047 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1048 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
1049 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1050 #if (GTK_MINOR_VERSION >= 10)
1051 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
1052 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
1054 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
1055 deserialize_type, TRUE);
1057 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1059 priv->isearch_toolbar = modest_toolkit_factory_create_isearch_toolbar (modest_runtime_get_toolkit_factory (),
1061 gtk_widget_set_no_show_all (priv->isearch_toolbar, TRUE);
1063 priv->scrollable = modest_toolkit_factory_create_scrollable (modest_runtime_get_toolkit_factory ());
1065 g_object_set (G_OBJECT (priv->scrollable), "horizontal-policy", GTK_POLICY_NEVER, NULL);
1067 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
1068 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1069 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), MODEST_MARGIN_HALF, 0,
1070 MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
1072 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
1073 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
1074 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
1076 modest_scrollable_add_with_viewport (MODEST_SCROLLABLE (priv->scrollable), window_align);
1077 gtk_widget_show_all (GTK_WIDGET(priv->scrollable));
1079 window_box = gtk_vbox_new (FALSE, 0);
1080 gtk_container_add (GTK_CONTAINER(obj), window_box);
1082 gtk_box_pack_start (GTK_BOX (window_box), priv->scrollable, TRUE, TRUE, 0);
1087 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
1089 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1091 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1092 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1093 priv->clipboard_change_handler_id))
1094 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1095 priv->clipboard_change_handler_id);
1096 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1097 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1098 priv->default_clipboard_change_handler_id))
1099 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1100 priv->default_clipboard_change_handler_id);
1102 if (priv->account_removed_handler_id &&
1103 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1104 priv->account_removed_handler_id))
1105 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1106 priv->account_removed_handler_id);
1110 modest_msg_edit_window_finalize (GObject *obj)
1112 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1114 g_object_unref (priv->custom_header_pairs);
1116 if (priv->max_chars_banner) {
1117 g_object_weak_unref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, obj);
1118 priv->max_chars_banner = FALSE;
1121 /* Sanity check: shouldn't be needed, the window mgr should
1122 call this function before */
1123 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1125 if (priv->font_dialog != NULL) {
1126 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1129 if (priv->clipboard_text != NULL) {
1130 g_free (priv->clipboard_text);
1131 priv->clipboard_text = NULL;
1134 if (priv->draft_msg != NULL) {
1135 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1136 if (TNY_IS_HEADER (header)) {
1137 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1138 modest_window_mgr_unregister_header (mgr, header);
1140 g_object_unref (priv->draft_msg);
1141 priv->draft_msg = NULL;
1143 if (priv->outbox_msg != NULL) {
1144 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1145 if (TNY_IS_HEADER (header)) {
1146 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1147 modest_window_mgr_unregister_header (mgr, header);
1149 g_object_unref (priv->outbox_msg);
1150 priv->outbox_msg = NULL;
1152 if (priv->correct_scroll_idle > 0) {
1153 g_source_remove (priv->correct_scroll_idle);
1154 priv->correct_scroll_idle = 0;
1156 if (priv->scroll_drag_timeout_id > 0) {
1157 g_source_remove (priv->scroll_drag_timeout_id);
1158 priv->scroll_drag_timeout_id = 0;
1160 if (priv->clipboard_owner_idle > 0) {
1161 g_source_remove (priv->clipboard_owner_idle);
1162 priv->clipboard_owner_idle = 0;
1164 if (priv->original_account_name)
1165 g_free (priv->original_account_name);
1166 if (priv->original_mailbox)
1167 g_free (priv->original_mailbox);
1168 g_free (priv->msg_uid);
1169 g_free (priv->last_search);
1170 g_slist_free (priv->font_items_group);
1171 g_free (priv->references);
1172 g_free (priv->in_reply_to);
1173 g_object_unref (priv->attachments);
1174 g_object_unref (priv->images);
1176 /* This had to stay alive for as long as the picker that used it: */
1177 modest_pair_list_free (priv->from_field_protos);
1179 G_OBJECT_CLASS(parent_class)->finalize (obj);
1183 pixbuf_size_prepared (GdkPixbufLoader *loader,
1186 ModestMsgEditWindow *self)
1188 gint new_height, new_width;
1191 new_height = height;
1195 if (width > IMAGE_MAX_WIDTH) {
1196 new_height = height * IMAGE_MAX_WIDTH / width;
1197 new_width = IMAGE_MAX_WIDTH;
1200 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1204 pixbuf_from_stream (TnyStream *stream,
1205 const gchar *mime_type,
1206 guint64 *stream_size,
1207 ModestMsgEditWindow *self)
1209 GdkPixbufLoader *loader;
1212 GError *error = NULL;
1216 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1218 if (loader == NULL) {
1223 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1225 modest_window_show_progress (MODEST_WINDOW (self), TRUE);
1227 tny_stream_reset (TNY_STREAM (stream));
1228 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1229 unsigned char read_buffer[128];
1231 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1233 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1236 /* Allow some UI responsiveness */
1237 while (gtk_events_pending ())
1238 gtk_main_iteration ();
1240 modest_window_show_progress (MODEST_WINDOW (self), FALSE);
1242 gdk_pixbuf_loader_close (loader, &error);
1245 g_error_free (error);
1246 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1248 g_object_ref (pixbuf);
1249 g_object_unref (loader);
1254 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1255 GdkPixbuf *new_pixbuf;
1257 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1258 gdk_pixbuf_get_width (pixbuf);
1259 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1260 g_object_unref (pixbuf);
1261 pixbuf = new_pixbuf;
1265 *stream_size = size;
1271 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1273 ModestMsgEditWindowPrivate *priv;
1276 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1278 g_object_ref (self);
1279 for (iter = tny_list_create_iterator (attachments);
1280 !tny_iterator_is_done (iter);
1281 tny_iterator_next (iter)) {
1282 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1283 const gchar *cid = tny_mime_part_get_content_id (part);
1284 const gchar *mime_type = tny_mime_part_get_content_type (part);
1285 if ((cid != NULL)&&(mime_type != NULL)) {
1286 guint64 stream_size;
1287 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1288 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1291 g_object_unref (stream);
1293 if (pixbuf != NULL) {
1294 priv->images_count ++;
1295 priv->images_size += stream_size;
1296 #ifndef MODEST_HAVE_LIBWPEDITOR_PLUS
1297 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1299 g_object_unref (pixbuf);
1302 g_object_unref (part);
1304 g_object_unref (iter);
1305 g_object_unref (self);
1309 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1311 TnyMimePart *parent = NULL;
1312 const gchar *content_type = NULL;
1313 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1315 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1317 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1318 parent = g_object_ref (msg);
1319 } else if (content_type && !g_ascii_strcasecmp (content_type, "multipart/mixed")) {
1320 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1323 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1324 iter = tny_list_create_iterator (parts);
1325 while (!tny_iterator_is_done (iter)) {
1327 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1328 content_type = tny_mime_part_get_content_type (part);
1329 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1333 g_object_unref (part);
1335 tny_iterator_next (iter);
1337 g_object_unref (iter);
1338 g_object_unref (parts);
1341 if (parent != NULL) {
1342 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1345 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1346 iter = tny_list_create_iterator (parts);
1347 while (!tny_iterator_is_done (iter)) {
1349 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1350 content_type = tny_mime_part_get_content_type (part);
1351 if (content_type && g_str_has_prefix (content_type, "image/")) {
1352 tny_list_prepend (priv->images, (GObject *) part);
1354 g_object_unref (part);
1355 tny_iterator_next (iter);
1357 g_object_unref (iter);
1358 g_object_unref (parts);
1359 g_object_unref (parent);
1364 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1367 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1369 for (iter = tny_list_create_iterator (attachments) ;
1370 !tny_iterator_is_done (iter);
1371 tny_iterator_next (iter)) {
1372 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1373 const gchar *cid = tny_mime_part_get_content_id (part);
1375 char *invalid = NULL;
1376 gint int_cid = strtol (cid, &invalid, 10);
1377 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1378 priv->next_cid = int_cid + 1;
1381 g_object_unref (part);
1383 g_object_unref (iter);
1387 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1390 gchar *to, *cc, *bcc, *subject;
1392 ModestMsgEditWindowPrivate *priv;
1393 ModestWindowPrivate *parent_priv;
1395 TnyHeaderFlags priority_flags;
1396 TnyFolder *msg_folder;
1397 gboolean is_html = FALSE;
1398 gboolean field_view_set;
1399 TnyList *orig_header_pairs;
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);
1535 orig_header_pairs = TNY_LIST (tny_simple_list_new ());
1536 tny_mime_part_get_header_pairs (TNY_MIME_PART (msg), orig_header_pairs);
1537 modest_msg_edit_window_set_custom_header_pairs (self, orig_header_pairs);
1538 g_object_unref (orig_header_pairs);
1546 #ifndef MODEST_TOOLKIT_HILDON2
1548 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1551 GList *item_children, *node;
1552 GtkWidget *bin_child;
1554 bin_child = gtk_bin_get_child (GTK_BIN(item));
1556 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1558 for (node = item_children; node != NULL; node = g_list_next (node)) {
1559 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1560 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1563 g_list_free (item_children);
1567 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1570 GList *item_children, *node;
1572 box = gtk_bin_get_child (GTK_BIN (item));
1573 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1574 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1576 for (node = item_children; node != NULL; node = g_list_next (node)) {
1577 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1578 if (GTK_IS_TOGGLE_BUTTON (node->data))
1579 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1580 else if (GTK_IS_BUTTON (node->data))
1581 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1583 g_list_free (item_children);
1588 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1590 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1591 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1592 GtkWidget *placeholder;
1593 GtkWidget *tool_item;
1598 GtkWidget *sizes_menu;
1602 #ifndef MODEST_TOOLKIT_HILDON2
1603 GSList *radio_group, *node;
1604 GtkWidget *fonts_menu;
1608 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1609 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1610 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar),
1611 #ifdef MODEST_TOOLKIT_HILDON2
1612 HILDON_ICON_SIZE_FINGER
1614 GTK_ICON_SIZE_LARGE_TOOLBAR
1617 modest_window_add_toolbar (MODEST_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1619 /* Font color placeholder */
1620 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1621 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1624 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1625 #ifdef MODEST_TOOLKIT_HILDON2
1626 priv->font_color_button = modest_color_button_new ();
1628 priv->font_color_button = gtk_color_button_new ();
1630 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1631 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1632 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1633 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1634 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1635 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1636 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1637 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1639 G_CALLBACK (modest_msg_edit_window_color_button_change),
1642 /* Font size and face placeholder */
1643 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1644 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1646 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, ""));
1647 priv->size_tool_button_label = gtk_label_new (NULL);
1648 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1649 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1650 size_text, "</span>", NULL);
1651 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1652 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1654 #ifdef MODEST_TOOLKIT_HILDON2
1655 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1657 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1658 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1659 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1660 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1661 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1662 gtk_widget_set_sensitive (arrow, FALSE);
1663 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1664 sizes_menu = gtk_menu_new ();
1665 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1666 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1669 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1670 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1672 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1676 if (wp_font_size[size_index] == 12)
1677 priv->current_size_index = size_index;
1681 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1682 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1683 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1684 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1685 priv->font_size_toolitem = tool_item;
1687 #ifdef MODEST_TOOLKIT_HILDON2
1689 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, ""));
1690 priv->font_tool_button_label = gtk_label_new (NULL);
1691 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1692 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1693 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1695 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1696 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1697 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1698 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1699 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1700 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1701 gtk_widget_set_sensitive (arrow, FALSE);
1702 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1704 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1705 priv->font_tool_button_label = gtk_label_new (NULL);
1706 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1707 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1709 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1710 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1711 gtk_widget_show (priv->font_tool_button_label);
1712 gtk_widget_show (GTK_WIDGET (tool_item));
1713 fonts_menu = gtk_menu_new ();
1716 #ifdef MODEST_TOOLKIT_HILDON2
1717 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1718 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1721 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1723 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1724 0, wp_get_font_name (font_index),
1727 if (font_index == DEFAULT_FONT)
1728 priv->current_face_index = font_index;
1730 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1731 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1732 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1733 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1734 priv->font_face_toolitem = tool_item;
1736 priv->font_items_group = NULL;
1738 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1739 GtkWidget *font_menu_item;
1740 GtkWidget *child_label;
1742 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1743 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1744 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1745 wp_get_font_name (font_index), "</span>", NULL);
1746 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1749 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1750 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1751 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1752 gtk_widget_show (font_menu_item);
1754 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1757 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1758 GtkWidget *item = (GtkWidget *) node->data;
1759 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1762 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1763 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1764 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1765 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1766 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1767 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1768 priv->font_face_toolitem = tool_item;
1771 /* Set expand and homogeneous for remaining items */
1772 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1773 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1774 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1775 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1776 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1777 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1778 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsInsertImage");
1779 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1780 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1782 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1783 will not show the tool items added to the placeholders) */
1784 gtk_widget_show_all (parent_priv->toolbar);
1786 /* Set the no show all *after* showing all items. We do not
1787 want the toolbar to be shown with a show all because it
1788 could go against the gconf setting regarding showing or not
1789 the toolbar of the editor window */
1790 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1796 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1799 ModestWindowPrivate *parent_priv;
1800 ModestMsgEditWindowPrivate *priv;
1801 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1802 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1803 ModestWindowMgr *mgr = NULL;
1805 g_return_val_if_fail (msg, NULL);
1806 g_return_val_if_fail (account_name, NULL);
1808 mgr = modest_runtime_get_window_mgr ();
1810 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1812 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1813 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1815 /* Menubar. Update the state of some toggles */
1816 priv->from_field_protos = get_transports ();
1817 priv->original_mailbox = NULL;
1818 modest_selector_set_pair_list (priv->from_field, priv->from_field_protos);
1819 modest_selector_set_active_id (priv->from_field, (gpointer) account_name);
1820 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
1821 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1822 modest_selector_set_active_id (priv->from_field, (gpointer) mailbox);
1823 priv->original_mailbox = g_strdup (mailbox);
1824 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1825 /* We set the first mailbox as the active mailbox */
1826 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1827 if (priv->original_mailbox != NULL)
1828 modest_selector_set_active_id (priv->from_field,
1829 (gpointer) priv->original_mailbox);
1831 modest_selector_set_active_id (priv->from_field,
1832 (gpointer) account_name);
1834 modest_selector_set_active_id (priv->from_field, (gpointer) account_name);
1836 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
1837 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1838 if (!GTK_IS_COMBO_BOX (priv->from_field)) {
1839 #ifdef HILDON_TOOLKIT_HILDON2
1840 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1842 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1843 hildon_touch_selector_get_current_text
1844 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1847 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1848 modest_window_add_toolbar (MODEST_WINDOW (obj), GTK_TOOLBAR (priv->isearch_toolbar));
1851 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1853 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1855 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1856 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1858 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1860 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1861 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1862 /* Add common dimming rules */
1863 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1864 modest_msg_edit_window_toolbar_dimming_entries,
1865 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1866 MODEST_WINDOW (obj));
1867 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1868 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1869 MODEST_WINDOW (obj));
1870 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1871 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1872 MODEST_WINDOW (obj));
1873 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1874 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1875 MODEST_WINDOW (obj));
1876 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1877 G_CALLBACK (modest_ui_dimming_rules_on_send),
1878 MODEST_WINDOW (obj));
1879 /* Insert dimming rules group for this window */
1880 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1881 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1883 /* Setup app menu */
1884 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1886 /* Checks the dimming rules */
1887 g_object_unref (toolbar_rules_group);
1888 g_object_unref (clipboard_rules_group);
1889 gtk_widget_hide (priv->priority_icon);
1890 gtk_widget_queue_resize (priv->subject_box);
1891 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1893 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1895 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1896 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1897 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1898 priv->update_caption_visibility = TRUE;
1900 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1902 /* Track account-removed signal, this window should be closed
1903 in the case we're creating a mail associated to the account
1905 priv->account_removed_handler_id =
1906 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1908 G_CALLBACK(on_account_removed),
1911 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1913 return (ModestWindow*) obj;
1917 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1919 GString **string_buffer = (GString **) user_data;
1921 *string_buffer = g_string_append (*string_buffer, buffer);
1927 * @result: A new string which should be freed with g_free().
1930 get_formatted_data (ModestMsgEditWindow *edit_window)
1932 ModestMsgEditWindowPrivate *priv;
1933 GString *string_buffer = g_string_new ("");
1935 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1937 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1939 modest_text_utils_hyperlinkify (string_buffer);
1941 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1943 return g_string_free (string_buffer, FALSE);
1948 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1951 const gchar *account_name;
1952 ModestMsgEditWindowPrivate *priv;
1953 TnyIterator *att_iter;
1954 const gchar *picker_active_id;
1956 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1958 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1960 picker_active_id = modest_selector_get_active_id (priv->from_field);
1961 g_return_val_if_fail (picker_active_id, NULL);
1962 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1964 /* don't free these (except from) */
1965 data = g_slice_new0 (MsgData);
1966 data->from = g_strdup ((gchar *) modest_selector_get_active_display_name (priv->from_field));
1967 data->account_name = g_strdup (account_name);
1968 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1969 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1970 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1971 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1972 data->references = g_strdup (priv->references);
1973 data->in_reply_to = g_strdup (priv->in_reply_to);
1974 if (priv->draft_msg) {
1975 data->draft_msg = g_object_ref (priv->draft_msg);
1976 } else if (priv->outbox_msg) {
1977 data->draft_msg = g_object_ref (priv->outbox_msg);
1979 data->draft_msg = NULL;
1982 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1984 gtk_text_buffer_get_bounds (buf, &b, &e);
1985 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1987 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1988 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1990 data->html_body = NULL;
1992 /* deep-copy the data */
1993 att_iter = tny_list_create_iterator (priv->attachments);
1994 data->attachments = NULL;
1995 while (!tny_iterator_is_done (att_iter)) {
1996 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1997 if (!(TNY_IS_MIME_PART(part))) {
1998 g_warning ("strange data in attachment list");
1999 g_object_unref (part);
2000 tny_iterator_next (att_iter);
2003 data->attachments = g_list_append (data->attachments,
2005 tny_iterator_next (att_iter);
2007 g_object_unref (att_iter);
2009 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
2010 att_iter = tny_list_create_iterator (priv->images);
2011 data->images = NULL;
2012 while (!tny_iterator_is_done (att_iter)) {
2013 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
2015 if (!(TNY_IS_MIME_PART(part))) {
2016 g_warning ("strange data in attachment list");
2017 g_object_unref (part);
2018 tny_iterator_next (att_iter);
2021 cid = tny_mime_part_get_content_id (part);
2023 gchar *image_tag_id;
2024 GtkTextTag *image_tag;
2026 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
2027 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
2028 g_free (image_tag_id);
2030 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
2032 ((gtk_text_iter_has_tag (&iter, image_tag))||
2033 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
2034 data->images = g_list_append (data->images,
2035 g_object_ref (part));
2037 g_object_unref (part);
2038 tny_iterator_next (att_iter);
2040 g_object_unref (att_iter);
2042 data->priority_flags = priv->priority_flags;
2043 data->custom_header_pairs = tny_list_copy (priv->custom_header_pairs);
2050 unref_gobject (GObject *obj, gpointer data)
2052 if (!G_IS_OBJECT(obj))
2054 g_object_unref (obj);
2058 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
2061 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
2069 g_free (data->from);
2070 g_free (data->subject);
2071 g_free (data->plain_body);
2072 g_free (data->html_body);
2073 g_free (data->account_name);
2074 g_free (data->references);
2075 g_free (data->in_reply_to);
2077 g_object_unref (data->custom_header_pairs);
2079 if (data->draft_msg != NULL) {
2080 g_object_unref (data->draft_msg);
2081 data->draft_msg = NULL;
2084 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
2085 g_list_free (data->attachments);
2086 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
2087 g_list_free (data->images);
2089 g_slice_free (MsgData, data);
2093 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
2095 guint64 *parts_size)
2097 ModestMsgEditWindowPrivate *priv;
2099 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2101 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
2103 /* TODO: add images */
2104 *parts_size += priv->images_size;
2105 *parts_count += priv->images_count;
2110 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
2113 ModestMsgEditWindowPrivate *priv = NULL;
2114 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
2116 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2118 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2120 return MODEST_MSG_EDIT_FORMAT_HTML;
2122 return MODEST_MSG_EDIT_FORMAT_TEXT;
2126 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
2127 ModestMsgEditFormat format)
2129 ModestMsgEditWindowPrivate *priv;
2130 ModestWindowPrivate *parent_priv;
2132 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2133 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2134 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
2137 case MODEST_MSG_EDIT_FORMAT_HTML:
2138 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2139 update_signature (self, priv->last_from_account, priv->last_from_account);
2140 if (parent_priv->toolbar)
2141 on_show_toolbar_button_toggled (priv->show_toolbar_button,
2142 MODEST_MSG_EDIT_WINDOW (self));
2144 case MODEST_MSG_EDIT_FORMAT_TEXT:
2145 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2146 if (parent_priv->toolbar)
2147 on_show_toolbar_button_toggled (priv->show_toolbar_button,
2148 MODEST_MSG_EDIT_WINDOW (self));
2151 g_return_if_reached ();
2155 ModestMsgEditFormatState *
2156 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
2158 ModestMsgEditFormatState *format_state = NULL;
2159 ModestMsgEditWindowPrivate *priv;
2160 WPTextBufferFormat *buffer_format;
2162 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
2164 buffer_format = g_new0 (WPTextBufferFormat, 1);
2165 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2167 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
2169 format_state = g_new0 (ModestMsgEditFormatState, 1);
2170 format_state->bold = buffer_format->bold&0x1;
2171 format_state->italics = buffer_format->italic&0x1;
2172 format_state->bullet = buffer_format->bullet&0x1;
2173 format_state->color = buffer_format->color;
2174 format_state->font_size = buffer_format->font_size;
2175 format_state->font_family = wp_get_font_name (buffer_format->font);
2176 format_state->justification = buffer_format->justification;
2177 g_free (buffer_format);
2179 return format_state;
2184 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
2185 const ModestMsgEditFormatState *format_state)
2187 ModestMsgEditWindowPrivate *priv;
2188 WPTextBufferFormat *buffer_format;
2189 WPTextBufferFormat *current_format;
2191 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2192 g_return_if_fail (format_state != NULL);
2194 buffer_format = g_new0 (WPTextBufferFormat, 1);
2195 current_format = g_new0 (WPTextBufferFormat, 1);
2197 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2198 gtk_widget_grab_focus (priv->msg_body);
2199 buffer_format->bold = (format_state->bold != FALSE);
2200 buffer_format->italic = (format_state->italics != FALSE);
2201 buffer_format->color = format_state->color;
2202 buffer_format->font_size = format_state->font_size;
2203 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
2204 buffer_format->justification = format_state->justification;
2205 buffer_format->bullet = format_state->bullet;
2207 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2209 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2210 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2211 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2212 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2213 buffer_format->cs.font = (buffer_format->font != current_format->font);
2214 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2215 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2217 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2218 if (buffer_format->cs.bold) {
2219 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2220 GINT_TO_POINTER (buffer_format->bold&0x1));
2222 if (buffer_format->cs.italic) {
2223 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2224 GINT_TO_POINTER (buffer_format->italic&0x1));
2226 if (buffer_format->cs.color) {
2227 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2228 GINT_TO_POINTER (&(buffer_format->color)));
2230 if (buffer_format->cs.font_size) {
2231 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2232 GINT_TO_POINTER (buffer_format->font_size));
2234 if (buffer_format->cs.justification) {
2235 switch (buffer_format->justification) {
2236 case GTK_JUSTIFY_LEFT:
2237 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2238 GINT_TO_POINTER(TRUE));
2240 case GTK_JUSTIFY_CENTER:
2241 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2242 GINT_TO_POINTER(TRUE));
2244 case GTK_JUSTIFY_RIGHT:
2245 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2246 GINT_TO_POINTER(TRUE));
2253 if (buffer_format->cs.font) {
2254 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2255 GINT_TO_POINTER (buffer_format->font));
2257 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2258 if (buffer_format->cs.bullet) {
2259 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2260 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2262 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2264 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2266 g_free (buffer_format);
2267 g_free (current_format);
2269 /* Check dimming rules */
2270 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2271 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2275 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2277 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2279 ModestWindowPrivate *parent_priv;
2280 ModestMsgEditWindowPrivate *priv;
2282 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2283 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2285 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2286 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2287 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2288 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2290 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2291 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2292 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2295 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2297 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2298 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2300 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2301 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2303 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2304 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2307 switch (buffer_format->justification)
2309 case GTK_JUSTIFY_LEFT:
2310 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2312 case GTK_JUSTIFY_CENTER:
2313 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2315 case GTK_JUSTIFY_RIGHT:
2316 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2323 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2325 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2326 G_CALLBACK (modest_msg_edit_window_color_button_change),
2328 #ifdef MODEST_TOOLKIT_HILDON2
2329 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2331 gtk_color_button_set_color (GTK_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2333 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2334 G_CALLBACK (modest_msg_edit_window_color_button_change),
2337 if (priv->current_size_index != buffer_format->font_size) {
2341 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2342 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2346 priv->current_size_index = buffer_format->font_size;
2348 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2349 markup = g_strconcat ("<span font_family='Sans'>",
2350 size_text, "</span>", NULL);
2352 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2356 gtk_tree_path_free (path);
2359 #ifdef MODEST_TOOLKIT_HILDON2
2360 if (priv->current_face_index != buffer_format->font) {
2364 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2365 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2369 priv->current_face_index = buffer_format->font;
2370 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2371 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2372 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2379 GtkWidget *new_font_menuitem;
2380 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
2381 buffer_format->font))->data);
2382 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
2386 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2387 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2388 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2390 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2391 G_CALLBACK (modest_msg_edit_window_font_change),
2393 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2394 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2395 G_CALLBACK (modest_msg_edit_window_font_change),
2400 g_free (buffer_format);
2406 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2408 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2409 ModestMsgEditWindowPrivate *priv;
2410 GtkWidget *dialog = NULL;
2412 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2413 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2415 #ifdef MODEST_TOOLKIT_HILDON2
2416 dialog = hildon_color_chooser_new ();
2417 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2418 g_free (buffer_format);
2420 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2422 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2423 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2426 gtk_widget_destroy (dialog);
2428 dialog = gtk_color_selection_dialog_new (NULL);
2429 GtkWidget *selection;
2431 g_object_get (G_OBJECT (dialog), "color_selection", &selection, NULL);
2432 gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (selection), &(buffer_format->color));
2433 gtk_color_selection_set_previous_color (GTK_COLOR_SELECTION (selection), &(buffer_format->color));
2434 g_free (buffer_format);
2436 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2438 gtk_color_selection_get_current_color (GTK_COLOR_SELECTION(selection), &col);
2439 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2442 gtk_widget_destroy (dialog);
2449 create_stream_for_uri (const gchar* uri)
2454 TnyStream *result = NULL;
2456 GnomeVFSHandle *handle = NULL;
2457 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2458 if (test == GNOME_VFS_OK) {
2459 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2460 /* Streams over OBEX (Bluetooth) are not seekable but
2461 * we expect them to be (we might need to read them
2462 * several times). So if this is a Bluetooth URI just
2463 * read the whole file into memory (this is not a fast
2464 * protocol so we can assume that these files are not
2465 * going to be very big) */
2466 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2467 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2468 TnyStream *memstream = tny_camel_mem_stream_new ();
2469 tny_stream_write_to_stream (vfssstream, memstream);
2470 g_object_unref (vfssstream);
2473 result = vfssstream;
2481 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2484 ModestMsgEditWindowPrivate *priv;
2485 GtkWidget *dialog = NULL;
2487 GSList *uris = NULL;
2488 GSList *uri_node = NULL;
2490 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2492 dialog = modest_toolkit_factory_create_file_chooser_dialog (modest_runtime_get_toolkit_factory (),
2493 _("mcen_ia_select_inline_image_title"),
2494 (GtkWindow *) window,
2495 GTK_FILE_CHOOSER_ACTION_OPEN);
2496 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2498 #ifdef MODEST_TOOLKIT_HILDON2
2499 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2502 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2503 GTK_WINDOW (dialog), GTK_WINDOW (window));
2505 response = gtk_dialog_run (GTK_DIALOG (dialog));
2507 case GTK_RESPONSE_OK:
2509 gchar *current_folder;
2510 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2511 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2512 if (current_folder && current_folder != '\0') {
2514 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2515 current_folder, &err);
2517 g_debug ("Error storing latest used folder: %s", err->message);
2521 g_free (current_folder);
2527 gtk_widget_destroy (dialog);
2529 g_object_ref (window);
2530 /* The operation could take some time so allow the dialog to be closed */
2531 while (gtk_events_pending ())
2532 gtk_main_iteration ();
2534 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2536 GnomeVFSHandle *handle = NULL;
2537 GnomeVFSResult result;
2538 GtkTextIter position;
2539 GtkTextMark *insert_mark;
2541 uri = (const gchar *) uri_node->data;
2542 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2543 if (result == GNOME_VFS_OK) {
2545 GnomeVFSFileInfo *info;
2546 gchar *filename, *basename, *escaped_filename;
2547 TnyMimePart *mime_part;
2549 const gchar *mime_type = NULL;
2550 GnomeVFSURI *vfs_uri;
2551 guint64 stream_size;
2553 gnome_vfs_close (handle);
2554 vfs_uri = gnome_vfs_uri_new (uri);
2556 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2557 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2558 g_free (escaped_filename);
2559 gnome_vfs_uri_unref (vfs_uri);
2560 info = gnome_vfs_file_info_new ();
2562 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2563 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2565 mime_type = gnome_vfs_file_info_get_mime_type (info);
2567 mime_part = tny_platform_factory_new_mime_part
2568 (modest_runtime_get_platform_factory ());
2570 TnyStream *stream = create_stream_for_uri (uri);
2572 if (stream == NULL) {
2574 modest_platform_information_banner (NULL, NULL,
2575 _FM_OPENING_NOT_ALLOWED);
2577 g_object_unref (mime_part);
2578 gnome_vfs_file_info_unref (info);
2582 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2584 content_id = g_strdup_printf ("%d", priv->next_cid);
2585 tny_mime_part_set_content_id (mime_part, content_id);
2586 g_free (content_id);
2589 basename = g_path_get_basename (filename);
2590 tny_mime_part_set_filename (mime_part, basename);
2593 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2595 if (pixbuf != NULL) {
2596 priv->images_size += stream_size;
2597 priv->images_count ++;
2598 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2599 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2600 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2601 tny_mime_part_get_content_id (mime_part), pixbuf);
2602 g_object_unref (pixbuf);
2604 tny_list_prepend (priv->images, (GObject *) mime_part);
2605 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2607 modest_platform_information_banner (NULL, NULL,
2608 _("mail_ib_file_operation_failed"));
2612 g_object_unref (mime_part);
2613 gnome_vfs_file_info_unref (info);
2617 g_object_unref (window);
2621 on_attach_file_response (GtkDialog *dialog,
2625 GSList *uris = NULL;
2627 GnomeVFSFileSize total_size, allowed_size;
2628 ModestMsgEditWindow *window;
2629 ModestMsgEditWindowPrivate *priv;
2634 case GTK_RESPONSE_OK:
2636 gchar *current_folder;
2638 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2639 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2640 if (current_folder && current_folder != '\0') {
2642 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2643 current_folder, &err);
2645 g_debug ("Error storing latest used folder: %s", err->message);
2649 g_free (current_folder);
2656 window = MODEST_MSG_EDIT_WINDOW (user_data);
2657 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2659 /* allowed size is the maximum size - what's already there */
2660 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2661 &att_num, &att_size);
2662 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2665 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2667 const gchar *uri = (const gchar *) uri_node->data;
2670 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2672 if (total_size > allowed_size) {
2673 g_debug ("%s: total size: %u",
2674 __FUNCTION__, (unsigned int)total_size);
2677 allowed_size -= total_size;
2679 g_slist_foreach (uris, (GFunc) g_free, NULL);
2680 g_slist_free (uris);
2682 gtk_widget_destroy (GTK_WIDGET (dialog));
2686 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2688 GtkWidget *dialog = NULL;
2689 ModestMsgEditWindowPrivate *priv;
2692 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2694 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2696 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2699 dialog = modest_toolkit_factory_create_file_chooser_dialog (modest_runtime_get_toolkit_factory (),
2700 _("mcen_ia_select_attachment_title"),
2701 (GtkWindow *) window,
2702 GTK_FILE_CHOOSER_ACTION_OPEN);
2703 conf_folder = modest_conf_get_string (modest_runtime_get_conf (),
2704 MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2705 if (conf_folder && conf_folder[0] != '\0') {
2706 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2709 /* Set the default folder to documents folder */
2710 docs_folder = (gchar *) g_strdup(g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
2711 #ifdef MODEST_TOOLKIT_HILDON2
2714 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2715 ".documents", NULL);
2718 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2719 g_free (docs_folder);
2721 g_free (conf_folder);
2722 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2723 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2724 GTK_WINDOW (dialog), GTK_WINDOW (window));
2726 /* Connect to response & show */
2727 g_signal_connect (dialog, "response",
2728 G_CALLBACK (on_attach_file_response), window);
2729 gtk_widget_show (dialog);
2734 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2736 GnomeVFSFileSize allowed_size)
2739 GnomeVFSHandle *handle = NULL;
2740 ModestMsgEditWindowPrivate *priv;
2741 GnomeVFSResult result;
2742 GnomeVFSFileSize size = 0;
2743 g_return_val_if_fail (window, 0);
2744 g_return_val_if_fail (uri, 0);
2746 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2748 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2749 if (result == GNOME_VFS_OK) {
2750 TnyMimePart *mime_part;
2752 const gchar *mime_type = NULL;
2754 gchar *escaped_filename;
2757 GnomeVFSFileInfo *info;
2758 GnomeVFSURI *vfs_uri;
2760 gnome_vfs_close (handle);
2761 vfs_uri = gnome_vfs_uri_new (uri);
2764 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2765 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2766 g_free (escaped_filename);
2767 gnome_vfs_uri_unref (vfs_uri);
2769 info = gnome_vfs_file_info_new ();
2771 if (gnome_vfs_get_file_info (uri,
2773 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2775 mime_type = gnome_vfs_file_info_get_mime_type (info);
2776 mime_part = tny_platform_factory_new_mime_part
2777 (modest_runtime_get_platform_factory ());
2779 /* try to get the attachment's size; this may fail for weird
2780 * file systems, like obex, upnp... */
2781 if (allowed_size != 0 &&
2782 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2784 if (size > allowed_size) {
2785 modest_platform_information_banner (NULL, NULL,
2786 _("mail_ib_error_attachment_size"));
2791 g_debug ("%s: could not get attachment size", __FUNCTION__);
2793 stream = create_stream_for_uri (uri);
2795 if (stream == NULL) {
2797 modest_platform_information_banner (NULL, NULL, _FM_OPENING_NOT_ALLOWED);
2799 g_object_unref (mime_part);
2801 gnome_vfs_file_info_unref (info);
2805 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2806 g_object_unref (stream);
2808 content_id = g_strdup_printf ("%d", priv->next_cid);
2809 tny_mime_part_set_content_id (mime_part, content_id);
2810 g_free (content_id);
2813 basename = g_path_get_basename (filename);
2814 tny_mime_part_set_filename (mime_part, basename);
2817 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2818 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2820 info->size == 0, info->size);
2821 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2822 gtk_widget_show_all (priv->attachments_caption);
2823 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2825 g_object_unref (mime_part);
2826 gnome_vfs_file_info_unref (info);
2833 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2836 ModestMsgEditWindowPrivate *priv;
2839 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2840 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2842 if (att_list == NULL) {
2843 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2844 if (!modest_toolkit_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2845 g_object_unref (att_list);
2849 g_object_ref (att_list);
2852 if (tny_list_get_length (att_list) == 0) {
2853 modest_platform_system_banner (NULL, NULL, _("TODO: no attachments selected to remove"));
2855 gboolean dialog_response;
2856 gchar *message = NULL;
2857 gchar *filename = NULL;
2859 if (tny_list_get_length (att_list) == 1) {
2861 iter = tny_list_create_iterator (att_list);
2862 part = (TnyMimePart *) tny_iterator_get_current (iter);
2863 g_object_unref (iter);
2864 if (TNY_IS_MSG (part)) {
2865 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2867 filename = tny_header_dup_subject (header);
2868 g_object_unref (header);
2870 if (filename == NULL) {
2871 filename = g_strdup (_("mail_va_no_subject"));
2874 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2876 g_object_unref (part);
2878 filename = g_strdup ("");
2880 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2881 "emev_nc_delete_attachments",
2882 tny_list_get_length (att_list)), filename);
2885 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2889 if (dialog_response != GTK_RESPONSE_OK) {
2890 g_object_unref (att_list);
2894 for (iter = tny_list_create_iterator (att_list);
2895 !tny_iterator_is_done (iter);
2896 tny_iterator_next (iter)) {
2897 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2898 const gchar *att_id;
2899 tny_list_remove (priv->attachments, (GObject *) mime_part);
2901 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2903 if (tny_list_get_length (priv->attachments) == 0)
2904 gtk_widget_hide (priv->attachments_caption);
2905 att_id = tny_mime_part_get_content_id (mime_part);
2907 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2909 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2910 g_object_unref (mime_part);
2912 g_object_unref (iter);
2915 g_object_unref (att_list);
2917 /* if the last attachment has been removed, focus the Subject: field */
2918 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2919 gtk_widget_grab_focus (priv->subject_field);
2923 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2926 ModestMsgEditWindowPrivate *priv;
2929 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2931 gtk_color_button_get_color (GTK_COLOR_BUTTON(priv->font_color_button), &new_color);
2933 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) &new_color);
2935 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2938 #ifndef MODEST_TOOLKIT_HILDON2
2940 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2943 ModestMsgEditWindowPrivate *priv;
2944 gint new_font_index;
2945 ModestMsgEditWindow *window;
2948 window = MODEST_MSG_EDIT_WINDOW (userdata);
2949 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2950 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2952 if (gtk_check_menu_item_get_active (menu_item)) {
2955 label = gtk_bin_get_child (GTK_BIN (menu_item));
2957 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2959 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2960 GINT_TO_POINTER(new_font_index)))
2961 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2963 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2964 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2965 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2972 font_size_clicked (GtkToolButton *button,
2973 ModestMsgEditWindow *window)
2975 #ifdef MODEST_TOOLKIT_HILDON2
2976 ModestMsgEditWindowPrivate *priv;
2977 GtkWidget *selector, *dialog;
2979 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2981 selector = hildon_touch_selector_new ();
2982 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2983 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2985 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2986 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2987 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2989 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2993 WPTextBufferFormat format;
2995 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2997 memset (&format, 0, sizeof (format));
2998 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
3000 format.cs.font_size = TRUE;
3001 format.cs.text_position = TRUE;
3002 format.cs.font = TRUE;
3003 format.font_size = new_index;
3004 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
3006 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
3007 GINT_TO_POINTER (new_index)))
3008 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
3010 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
3011 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
3012 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
3013 size_text, "</span>", NULL);
3015 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
3019 gtk_widget_destroy (dialog);
3021 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
3025 #ifdef MODEST_TOOLKIT_HILDON2
3027 font_face_clicked (GtkToolButton *button,
3028 ModestMsgEditWindow *window)
3030 ModestMsgEditWindowPrivate *priv;
3031 GtkWidget *selector, *dialog;
3032 GtkCellRenderer *renderer;
3034 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3036 selector = hildon_touch_selector_new ();
3037 renderer = gtk_cell_renderer_text_new ();
3038 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
3039 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
3040 renderer, "family", 0, "text", 0, NULL);
3041 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
3043 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
3044 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
3045 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
3047 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
3048 gint new_font_index;
3052 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
3053 path = gtk_tree_path_new_from_indices (new_font_index, -1);
3054 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
3058 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
3060 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
3061 GINT_TO_POINTER(new_font_index)))
3062 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
3064 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
3065 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
3067 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
3071 gtk_tree_path_free (path);
3074 gtk_widget_destroy (dialog);
3076 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
3081 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
3084 ModestMsgEditWindowPrivate *priv = NULL;
3085 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3087 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3088 if (!priv->update_caption_visibility)
3091 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
3093 gtk_widget_show (priv->cc_caption);
3095 gtk_widget_hide (priv->cc_caption);
3097 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
3101 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
3104 ModestMsgEditWindowPrivate *priv = NULL;
3105 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3107 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3108 if (!priv->update_caption_visibility)
3111 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
3113 gtk_widget_show (priv->bcc_caption);
3115 gtk_widget_hide (priv->bcc_caption);
3117 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
3121 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
3122 ModestRecptEditor *editor)
3124 ModestMsgEditWindowPrivate *priv;
3126 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3127 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
3129 /* we check for low-mem; in that case, show a warning, and don't allow
3130 * for the addressbook
3132 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3135 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3137 if (editor == NULL) {
3138 GtkWidget *view_focus, *parent;
3139 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
3141 /* This code should be kept in sync with ModestRecptEditor. The
3142 textview inside the recpt editor is the one that really gets the
3143 focus. As it's inside a scrolled window, and this one inside the
3144 hbox recpt editor inherits from, we'll need to go up in the
3145 hierarchy to know if the text view is part of the recpt editor
3146 or if it's a different text entry */
3147 parent = gtk_widget_get_parent (view_focus);
3148 if (parent && MODEST_IS_RECPT_EDITOR (parent))
3149 editor = MODEST_RECPT_EDITOR (parent);
3152 editor = MODEST_RECPT_EDITOR (priv->to_field);
3155 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
3159 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
3161 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3163 modest_msg_edit_window_open_addressbook (window, NULL);
3167 modest_msg_edit_window_show_toolbar (ModestWindow *self,
3168 gboolean show_toolbar)
3170 ModestWindowPrivate *parent_priv;
3171 ModestMsgEditWindowPrivate *priv;
3173 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
3174 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3175 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
3177 /* We can not just use the code of
3178 modest_msg_edit_window_setup_toolbar because it has a
3179 mixture of both initialization and creation code. */
3181 gint current_format;
3182 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3183 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3184 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3185 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3187 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
3190 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3192 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, show_toolbar, NULL);
3193 if (modest_togglable_get_active (priv->show_toolbar_button) != show_toolbar) {
3194 modest_togglable_set_active (priv->show_toolbar_button, show_toolbar);
3199 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
3200 TnyHeaderFlags priority_flags)
3202 ModestMsgEditWindowPrivate *priv;
3203 ModestWindowPrivate *parent_priv;
3205 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3207 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3208 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3210 if (priv->priority_flags != priority_flags) {
3211 GtkAction *priority_action = NULL;
3213 priv->priority_flags = priority_flags;
3215 switch (priority_flags) {
3216 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3217 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3218 MODEST_HEADER_ICON_HIGH,
3219 #ifdef MODEST_TOOLKIT_HILDON2
3220 HILDON_ICON_SIZE_SMALL
3222 GTK_ICON_SIZE_BUTTON
3225 gtk_widget_show (priv->priority_icon);
3226 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3227 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
3229 case TNY_HEADER_FLAG_LOW_PRIORITY:
3230 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3231 MODEST_HEADER_ICON_LOW,
3232 #ifdef MODEST_TOOLKIT_HILDON2
3233 HILDON_ICON_SIZE_SMALL
3235 GTK_ICON_SIZE_BUTTON
3238 gtk_widget_show (priv->priority_icon);
3239 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3240 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3243 gtk_widget_hide (priv->priority_icon);
3244 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3245 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3248 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3249 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3251 gtk_widget_queue_resize (priv->subject_box);
3255 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3258 ModestMsgEditWindowPrivate *priv;
3259 ModestWindowPrivate *parent_priv;
3260 gint current_format;
3262 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3264 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3265 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3267 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3268 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3270 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3272 if (current_format != file_format) {
3273 switch (file_format) {
3274 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3275 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3276 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3277 update_signature (window, priv->last_from_account, priv->last_from_account);
3278 if (parent_priv->toolbar)
3279 on_show_toolbar_button_toggled (priv->show_toolbar_button,
3280 MODEST_MSG_EDIT_WINDOW (window));
3282 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3285 response = modest_platform_run_confirmation_dialog (NULL, _("emev_nc_formatting_lost"));
3286 if (response == GTK_RESPONSE_OK) {
3287 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3288 if (parent_priv->toolbar)
3289 on_show_toolbar_button_toggled (priv->show_toolbar_button,
3290 MODEST_MSG_EDIT_WINDOW (window));
3292 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3293 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3298 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3299 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3300 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3305 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3307 #ifdef MODEST_TOOLKIT_HILDON2
3309 ModestMsgEditWindowPrivate *priv;
3310 WPTextBufferFormat oldfmt, fmt;
3311 gint old_position = 0;
3315 GdkColor *color = NULL;
3316 gboolean bold, bold_set, italic, italic_set;
3317 gboolean underline, underline_set;
3318 gboolean strikethrough, strikethrough_set;
3319 gboolean position_set;
3320 gboolean font_size_set, font_set, color_set;
3323 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3324 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3326 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3327 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3328 GTK_WINDOW(dialog), GTK_WINDOW (window));
3330 /* First we get the currently selected font information */
3331 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3333 switch (oldfmt.text_position) {
3334 case TEXT_POSITION_NORMAL:
3337 case TEXT_POSITION_SUPERSCRIPT:
3345 g_object_set (G_OBJECT (dialog),
3346 "bold", oldfmt.bold != FALSE,
3347 "bold-set", !oldfmt.cs.bold,
3348 "underline", oldfmt.underline != FALSE,
3349 "underline-set", !oldfmt.cs.underline,
3350 "italic", oldfmt.italic != FALSE,
3351 "italic-set", !oldfmt.cs.italic,
3352 "strikethrough", oldfmt.strikethrough != FALSE,
3353 "strikethrough-set", !oldfmt.cs.strikethrough,
3354 "color", &oldfmt.color,
3355 "color-set", !oldfmt.cs.color,
3356 "size", wp_font_size[oldfmt.font_size],
3357 "size-set", !oldfmt.cs.font_size,
3358 "position", old_position,
3359 "position-set", !oldfmt.cs.text_position,
3360 "family", wp_get_font_name (oldfmt.font),
3361 "family-set", !oldfmt.cs.font,
3364 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3365 GTK_WINDOW (dialog), GTK_WINDOW (window));
3366 gtk_widget_show_all (dialog);
3367 priv->font_dialog = dialog;
3368 response = gtk_dialog_run (GTK_DIALOG (dialog));
3369 priv->font_dialog = NULL;
3370 if (response == GTK_RESPONSE_OK) {
3372 g_object_get( dialog,
3374 "bold-set", &bold_set,
3375 "underline", &underline,
3376 "underline-set", &underline_set,
3378 "italic-set", &italic_set,
3379 "strikethrough", &strikethrough,
3380 "strikethrough-set", &strikethrough_set,
3382 "color-set", &color_set,
3384 "size-set", &font_size_set,
3385 "family", &font_name,
3386 "family-set", &font_set,
3387 "position", &position,
3388 "position-set", &position_set,
3393 if (response == GTK_RESPONSE_OK) {
3394 memset(&fmt, 0, sizeof(fmt));
3400 fmt.italic = italic;
3401 fmt.cs.italic = TRUE;
3403 if (underline_set) {
3404 fmt.underline = underline;
3405 fmt.cs.underline = TRUE;
3407 if (strikethrough_set) {
3408 fmt.strikethrough = strikethrough;
3409 fmt.cs.strikethrough = TRUE;
3414 ? TEXT_POSITION_NORMAL
3415 : ( ( position == 1 )
3416 ? TEXT_POSITION_SUPERSCRIPT
3417 : TEXT_POSITION_SUBSCRIPT );
3418 fmt.cs.text_position = TRUE;
3419 fmt.font_size = oldfmt.font_size;
3423 fmt.cs.color = TRUE;
3426 fmt.font = wp_get_font_index(font_name,
3431 if (font_size_set) {
3432 fmt.cs.font_size = TRUE;
3433 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3435 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3436 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3438 gtk_widget_destroy (dialog);
3440 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3445 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3447 ModestMsgEditWindowPrivate *priv;
3448 ModestWindowPrivate *parent_priv;
3449 gboolean was_rich_text, is_rich_text;
3451 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3452 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3453 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3455 was_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3457 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3459 is_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3461 if (parent_priv->toolbar && was_rich_text != is_rich_text) {
3462 on_show_toolbar_button_toggled (priv->show_toolbar_button,
3463 MODEST_MSG_EDIT_WINDOW (window));
3466 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3467 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3471 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3473 ModestMsgEditWindowPrivate *priv;
3475 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3476 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3478 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3480 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3481 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3486 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3488 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3490 priv->can_undo = can_undo;
3494 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3496 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3498 priv->can_redo = can_redo;
3502 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3504 ModestMsgEditWindowPrivate *priv;
3505 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3506 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3508 return priv->can_undo;
3512 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3514 ModestMsgEditWindowPrivate *priv;
3515 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3516 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3518 return priv->can_redo;
3523 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3526 GtkTextIter match_start, match_end;
3528 if (image_id == NULL)
3531 gtk_text_buffer_get_start_iter (buffer, &iter);
3533 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3534 GSList *tags = gtk_text_iter_get_tags (&match_start);
3536 for (node = tags; node != NULL; node = g_slist_next (node)) {
3537 GtkTextTag *tag = (GtkTextTag *) node->data;
3538 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3539 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3540 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3542 offset = gtk_text_iter_get_offset (&match_start);
3543 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3544 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3548 gtk_text_iter_forward_char (&iter);
3553 message_is_empty (ModestMsgEditWindow *window)
3555 ModestMsgEditWindowPrivate *priv = NULL;
3557 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3558 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3560 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3561 * so we can ignore markup.
3563 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3566 count = gtk_text_buffer_get_char_count (buf);
3572 msg_body_focus (GtkWidget *focus,
3573 GdkEventFocus *event,
3577 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3578 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3579 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3584 recpt_field_changed (GtkTextBuffer *buffer,
3585 ModestMsgEditWindow *editor)
3587 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3588 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3592 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3594 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3595 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3599 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3602 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3603 GtkTextBuffer *buffer;
3605 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3606 gtk_text_buffer_set_modified (buffer, modified);
3607 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3608 gtk_text_buffer_set_modified (buffer, modified);
3609 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3610 gtk_text_buffer_set_modified (buffer, modified);
3611 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3615 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3617 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3618 const char *account_name;
3619 GtkTextBuffer *buffer;
3621 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3622 if (gtk_text_buffer_get_modified (buffer))
3624 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3625 if (gtk_text_buffer_get_modified (buffer))
3627 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3628 if (gtk_text_buffer_get_modified (buffer))
3630 if (gtk_text_buffer_get_modified (priv->text_buffer))
3633 account_name = modest_selector_get_active_id (priv->from_field);
3634 if (priv->original_mailbox) {
3635 if (!account_name || strcmp (account_name, priv->original_mailbox))
3637 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3648 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3650 ModestMsgEditWindowPrivate *priv = NULL;
3651 GSList *address_list = NULL;
3652 gboolean no_to, no_cc, no_bcc;
3654 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3655 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3657 /* check if there's no recipient added */
3658 no_to = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)));
3659 no_cc = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field)));
3660 no_bcc = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field)));
3663 if (no_to && no_cc && no_bcc) {
3664 /* no recipient contents, then select contacts */
3665 modest_msg_edit_window_open_addressbook (window, NULL);
3670 g_object_ref (window);
3671 if (!no_to && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field),
3672 (add_to_addressbook) ? &address_list : NULL)) {
3673 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3674 g_object_unref (window);
3677 if (!no_cc && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field),
3678 (add_to_addressbook) ? &address_list : NULL)) {
3679 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3680 g_object_unref (window);
3683 if (!no_bcc && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field),
3684 (add_to_addressbook) ? &address_list : NULL)) {
3685 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3686 g_object_unref (window);
3690 /* Add contacts to address book */
3691 if (add_to_addressbook && address_list)
3692 modest_address_book_add_address_list (address_list);
3694 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3695 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3696 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3697 g_object_unref (window);
3704 modest_msg_edit_window_add_to_contacts (ModestMsgEditWindow *self)
3706 GSList *recipients = NULL;
3707 ModestMsgEditWindowPrivate *priv;
3708 gchar *joined, *after_remove, *to, *cc, *bcc;
3710 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3712 /* First of all check names */
3713 if (!modest_msg_edit_window_check_names (self, FALSE))
3716 if (!modest_msg_edit_window_has_pending_addresses (self))
3719 /* Don't add the from obviously */
3720 to = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->to_field));
3721 cc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->cc_field));
3722 bcc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->bcc_field));
3724 joined = modest_text_utils_join_addresses (NULL, to, cc, bcc);
3729 after_remove = modest_text_utils_remove_duplicate_addresses (joined);
3732 recipients = modest_text_utils_split_addresses_list (after_remove);
3733 g_free (after_remove);
3736 /* Offer the user to add recipients to the address book */
3737 modest_address_book_add_address_list_with_selector (recipients, (GtkWindow *) self);
3738 g_slist_foreach (recipients, (GFunc) g_free, NULL); g_slist_free (recipients);
3743 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3744 ModestMsgEditWindow *window)
3746 modest_msg_edit_window_offer_attach_file (window);
3750 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3752 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3754 return priv->clipboard_text;
3758 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3760 ModestMsgEditWindow *window)
3762 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3763 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3766 /* It could happen that the window was already closed */
3767 if (!GTK_WIDGET_VISIBLE (window))
3770 g_object_ref (window);
3771 text = gtk_clipboard_wait_for_text (selection_clipboard);
3773 if (priv->clipboard_text != NULL) {
3774 g_free (priv->clipboard_text);
3776 priv->clipboard_text = text;
3778 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3780 g_object_unref (window);
3783 static gboolean clipboard_owner_change_idle (gpointer userdata)
3785 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3786 ModestMsgEditWindowPrivate *priv;
3788 gdk_threads_enter ();
3789 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3790 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3792 priv->clipboard_owner_idle = 0;
3793 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3794 gdk_threads_leave ();
3800 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3802 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3803 if (priv->clipboard_owner_idle == 0) {
3804 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3805 clipboard_owner_change_idle,
3806 g_object_ref (window),
3812 subject_field_move_cursor (GtkEntry *entry,
3813 GtkMovementStep step,
3818 /* It could happen that the window was already closed */
3819 if (!GTK_WIDGET_VISIBLE (window))
3822 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3826 update_window_title (ModestMsgEditWindow *window)
3828 ModestMsgEditWindowPrivate *priv = NULL;
3829 const gchar *subject;
3831 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3832 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3833 if (subject == NULL || subject[0] == '\0')
3834 subject = _("mail_va_new_email");
3836 modest_window_set_title (MODEST_WINDOW (window), subject);
3842 body_insert_text (GtkTextBuffer *buffer,
3843 GtkTextIter *location,
3846 ModestMsgEditWindow *window)
3848 GtkTextIter end_iter;
3855 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3857 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3859 offset = gtk_text_iter_get_offset (&end_iter);
3860 line = gtk_text_iter_get_line (&end_iter);
3864 while (text_offset < text + len) {
3865 if (*text_offset == '\n')
3867 if (text_lines + line >= MAX_BODY_LINES) {
3868 len = text_offset - text;
3874 utf8_len = g_utf8_strlen (text, len);
3876 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3877 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3878 if (line <= MAX_BODY_LINES && offset < MAX_BODY_LENGTH)
3883 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3885 /* Prevent endless recursion */
3886 result = g_strndup (text, utf8_end - text);
3887 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3888 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3889 (gpointer) result, (gpointer) (utf8_end - text),
3891 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3895 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3896 if (priv->max_chars_banner == NULL) {
3897 #ifdef MODEST_TOOLKIT_HILDON2
3898 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3899 _CS_MAXIMUM_CHARACTERS_REACHED);
3900 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3907 subject_field_changed (GtkEditable *editable,
3908 ModestMsgEditWindow *window)
3910 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3911 update_window_title (window);
3912 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3913 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3914 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3917 subject_field_insert_text (GtkEditable *editable,
3919 gint new_text_length,
3921 ModestMsgEditWindow *window)
3923 GString *result = g_string_new ("");
3925 gint result_len = 0;
3926 const gchar *entry_text = NULL;
3929 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3930 old_length = g_utf8_strlen (entry_text, -1);
3932 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3933 gunichar c = g_utf8_get_char_validated (current, 8);
3934 /* Invalid unichar, stop */
3940 result = g_string_append_unichar (result, c);
3944 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3945 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3948 /* Prevent endless recursion */
3949 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3950 g_signal_emit_by_name (editable, "insert-text",
3951 (gpointer) result->str, (gpointer) result->len,
3952 (gpointer) position, (gpointer) window);
3953 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3957 if (result_len + old_length > 1000) {
3958 modest_platform_system_banner (GTK_WIDGET (window), NULL,
3959 _CS_MAXIMUM_CHARACTERS_REACHED);
3961 g_string_free (result, TRUE);
3965 modest_msg_edit_window_toggle_isearch_toolbar (ModestMsgEditWindow *window,
3968 ModestMsgEditWindowPrivate *priv = NULL;
3970 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3971 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3973 gtk_widget_set_no_show_all (priv->isearch_toolbar, FALSE);
3976 gtk_widget_show_all (priv->isearch_toolbar);
3977 modest_isearch_toolbar_highlight_entry (MODEST_ISEARCH_TOOLBAR (priv->isearch_toolbar), TRUE);
3979 gtk_widget_hide_all (priv->isearch_toolbar);
3980 gtk_widget_grab_focus (priv->msg_body);
3985 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3987 GtkTextIter *match_start,
3988 GtkTextIter *match_end)
3990 GtkTextIter end_iter;
3991 gchar *str_casefold;
3994 gchar *range_casefold;
3997 gboolean result = FALSE;
4004 gtk_text_iter_forward_to_end (&end_iter);
4006 str_casefold = g_utf8_casefold (str, -1);
4007 str_chars_n = strlen (str);
4009 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
4010 range_casefold = g_utf8_casefold (range_text, -1);
4011 range_chars_n = strlen (range_casefold);
4013 if (range_chars_n < str_chars_n) {
4014 g_free (str_casefold);
4015 g_free (range_text);
4016 g_free (range_casefold);
4020 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
4021 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
4022 if (!g_utf8_collate (range_subtext, str_casefold)) {
4023 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
4025 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
4026 match_start, match_end, NULL)) {
4027 g_debug ("Matched string with collate, but not matched in model");
4029 g_free (found_text);
4031 g_free (range_subtext);
4035 g_free (str_casefold);
4036 g_free (range_text);
4037 g_free (range_casefold);
4044 modest_msg_edit_window_isearch_toolbar_search (GtkWidget *widget,
4045 ModestMsgEditWindow *window)
4047 const gchar *current_search = NULL;
4048 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4050 GtkTextIter selection_start, selection_end;
4051 GtkTextIter match_start, match_end;
4052 gboolean continue_search = FALSE;
4054 if (message_is_empty (window)) {
4055 g_free (priv->last_search);
4056 priv->last_search = NULL;
4057 modest_platform_system_banner (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
4061 current_search = modest_isearch_toolbar_get_search (MODEST_ISEARCH_TOOLBAR (widget));
4062 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
4063 g_free (priv->last_search);
4064 priv->last_search = NULL;
4065 /* Information banner about empty search */
4066 modest_platform_system_banner (NULL, NULL, _CS_FIND_REP_ENTER_TEXT);
4070 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
4071 continue_search = TRUE;
4073 g_free (priv->last_search);
4074 priv->last_search = g_strdup (current_search);
4077 if (continue_search) {
4078 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
4079 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
4080 &match_start, &match_end);
4082 modest_platform_system_banner (NULL, NULL, _HL_IB_FIND_COMPLETE);
4084 GtkTextIter buffer_start;
4085 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
4086 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
4087 &match_start, &match_end);
4089 modest_platform_system_banner (NULL, NULL, _HL_IB_FIND_NO_MATCHES);
4092 /* Mark as selected the string found in search */
4094 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
4095 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
4096 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
4098 g_free (priv->last_search);
4099 priv->last_search = NULL;
4104 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
4106 ModestMsgEditWindowPrivate *priv;
4108 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
4113 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
4116 ModestMsgEditWindowPrivate *priv;
4118 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
4123 modest_msg_edit_window_isearch_toolbar_close (GtkWidget *widget,
4124 ModestMsgEditWindow *window)
4126 modest_msg_edit_window_toggle_isearch_toolbar (window, FALSE);
4130 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
4133 ModestMsgEditWindowPrivate *priv;
4134 TnyHeader *header = NULL;
4136 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4137 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
4139 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4141 if (priv->draft_msg != NULL) {
4142 g_object_unref (priv->draft_msg);
4145 if (draft != NULL) {
4146 g_object_ref (draft);
4147 header = tny_msg_get_header (draft);
4148 if (priv->msg_uid) {
4149 g_free (priv->msg_uid);
4150 priv->msg_uid = NULL;
4152 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
4155 priv->draft_msg = draft;
4159 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
4160 GtkTextIter *start, GtkTextIter *end,
4163 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
4164 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
4167 if (tag == NULL) return;
4168 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
4169 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
4170 replace_with_images (window, priv->images);
4175 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
4178 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4180 g_return_if_fail (TNY_IS_MIME_PART (part));
4181 tny_list_prepend (priv->attachments, (GObject *) part);
4182 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
4183 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
4184 gtk_widget_show_all (priv->attachments_caption);
4185 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
4189 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
4191 ModestMsgEditWindowPrivate *priv;
4193 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
4194 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4196 return priv->msg_uid;
4200 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
4201 ModestMsgEditWindowWidgetType widget_type)
4203 ModestMsgEditWindowPrivate *priv;
4205 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
4206 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
4208 switch (widget_type) {
4209 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
4210 return priv->msg_body;
4212 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
4213 return priv->to_field;
4215 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
4216 return priv->cc_field;
4218 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
4219 return priv->bcc_field;
4221 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
4222 return priv->subject_field;
4224 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
4225 return priv->attachments_view;
4233 remove_tags (WPTextBuffer *buffer)
4235 GtkTextIter start, end;
4237 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
4238 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
4240 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
4244 on_account_removed (TnyAccountStore *account_store,
4245 TnyAccount *account,
4248 /* Do nothing if it's a store account, because we use the
4249 transport to send the messages */
4250 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
4251 const gchar *parent_acc = NULL;
4252 const gchar *our_acc = NULL;
4254 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
4255 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
4256 /* Close this window if I'm showing a message of the removed account */
4257 if (strcmp (parent_acc, our_acc) == 0)
4258 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
4263 update_signature (ModestMsgEditWindow *self,
4264 const gchar *old_account,
4265 const gchar *new_account)
4267 ModestMsgEditWindowPrivate *priv;
4268 gboolean has_old_signature, has_new_signature;
4270 ModestAccountMgr *mgr;
4273 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4275 gtk_text_buffer_begin_user_action (priv->text_buffer);
4277 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
4278 mgr = modest_runtime_get_account_mgr ();
4282 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
4283 if (has_old_signature) {
4284 GtkTextIter match_start, match_end;
4286 MODEST_TEXT_UTILS_SIGNATURE_MARKER as it
4287 seems that the search has some problems
4288 with the blank space at the end */
4289 if (gtk_text_iter_forward_search (&iter, "--",
4290 GTK_TEXT_SEARCH_TEXT_ONLY,
4291 &match_start, NULL, NULL)) {
4292 gtk_text_buffer_get_end_iter (priv->text_buffer ,&match_end);
4293 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
4295 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
4296 &match_start, &match_end, NULL)) {
4300 gtk_text_buffer_get_end_iter (priv->text_buffer, &iter);
4305 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
4306 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
4307 if (has_new_signature) {
4310 gchar *full_signature = g_strconcat ((gtk_text_iter_starts_line (&iter)) ? "" : "\n",
4311 MODEST_TEXT_UTILS_SIGNATURE_MARKER, "\n",
4313 is_rich = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
4315 WPTextBufferFormat *fmt;
4316 GdkColor style_color;
4317 if (!gtk_style_lookup_color (GTK_WIDGET (self)->style, "SecondaryTextColor", &style_color)) {
4318 gdk_color_parse ("grey", &style_color);
4320 fmt = g_new0 (WPTextBufferFormat, 1);
4321 fmt->color = style_color;
4322 fmt->cs.color = 0x1;
4323 wp_text_buffer_insert_with_attribute (WP_TEXT_BUFFER (priv->text_buffer), &iter,
4327 g_free (full_signature);
4329 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4333 gtk_text_buffer_end_user_action (priv->text_buffer);
4336 static void update_branding (ModestMsgEditWindow *self,
4337 const gchar *new_account)
4339 ModestMsgEditWindowPrivate *priv;
4340 ModestAccountMgr *mgr;
4341 const GdkPixbuf *new_icon = NULL;
4342 gchar *new_label = NULL;
4343 gboolean show = FALSE;
4345 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4347 mgr = modest_runtime_get_account_mgr ();
4349 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4351 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4352 gtk_widget_show (priv->brand_icon);
4355 gtk_widget_hide (priv->brand_icon);
4358 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4359 gtk_widget_show (priv->brand_label);
4363 gtk_widget_hide (priv->brand_label);
4367 gtk_widget_show (priv->brand_container);
4369 gtk_widget_hide (priv->brand_container);
4373 from_field_changed (GtkWidget *button,
4374 ModestMsgEditWindow *self)
4376 ModestMsgEditWindowPrivate *priv;
4377 gchar *old_account, *new_account;
4379 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4381 old_account = priv->last_from_account;
4382 new_account = modest_selector_get_active_id (priv->from_field);
4385 g_warning ("%s, could not get the new account", __FUNCTION__);
4389 /* If the From is the same do nothing */
4390 if (old_account && new_account && !strcmp (old_account, new_account))
4393 priv->last_from_account = new_account;
4395 update_signature (self, old_account, new_account);
4396 update_branding (self, new_account);
4400 typedef struct _MessageSettingsHelper {
4401 ModestMsgEditWindow *window;
4402 GSList *priority_group;
4403 GSList *format_group;
4404 GtkToggleButton *current_priority;
4405 GtkToggleButton *current_format;
4406 } MessageSettingsHelper;
4409 on_priority_toggle (GtkToggleButton *button,
4410 MessageSettingsHelper *helper)
4413 ModestMsgEditWindowPrivate *priv;
4415 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4416 if (gtk_toggle_button_get_active (button)) {
4418 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4419 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4420 if ((node_button != button) &&
4421 gtk_toggle_button_get_active (node_button)) {
4422 gtk_toggle_button_set_active (node_button, FALSE);
4425 helper->current_priority = button;
4427 gboolean found = FALSE;
4428 /* If no one is active, activate it again */
4429 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4430 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4431 if (gtk_toggle_button_get_active (node_button)) {
4437 gtk_toggle_button_set_active (button, TRUE);
4443 on_format_toggle (GtkToggleButton *button,
4444 MessageSettingsHelper *helper)
4447 ModestMsgEditWindowPrivate *priv;
4449 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4450 if (gtk_toggle_button_get_active (button)) {
4452 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4453 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4454 if ((node_button != button) &&
4455 gtk_toggle_button_get_active (node_button)) {
4456 gtk_toggle_button_set_active (node_button, FALSE);
4459 helper->current_format = button;
4461 gboolean found = FALSE;
4462 /* If no one is active, activate it again */
4463 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4464 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4465 if (gtk_toggle_button_get_active (node_button)) {
4471 gtk_toggle_button_set_active (button, TRUE);
4478 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4483 GtkWidget *priority_hbox;
4484 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4485 GtkWidget *captioned;
4486 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4487 GtkWidget *format_hbox;
4488 GtkWidget *html_toggle, *text_toggle;
4489 ModestMsgEditWindowPrivate *priv;
4490 MessageSettingsHelper helper = {0,};
4492 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4493 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4494 helper.window = window;
4495 helper.priority_group = NULL;
4496 helper.format_group = NULL;
4498 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4499 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4501 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4502 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4503 _HL_DONE, GTK_RESPONSE_ACCEPT, NULL);
4504 vbox = gtk_vbox_new (FALSE, 0);
4505 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4506 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4507 gtk_container_add (GTK_CONTAINER (align), vbox);
4508 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4509 gtk_widget_show (align);
4510 gtk_widget_show (vbox);
4512 /* Priority toggles */
4513 priority_hbox = gtk_hbox_new (TRUE, 0);
4514 #ifdef MODEST_TOOLKIT_HILDON2
4515 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4517 high_toggle = gtk_toggle_button_new ();
4519 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4520 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4521 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4522 #ifdef MODEST_TOOLKIT_HILDON2
4523 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4525 medium_toggle = gtk_toggle_button_new ();
4527 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4528 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4529 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4530 #ifdef MODEST_TOOLKIT_HILDON2
4531 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4533 low_toggle = gtk_toggle_button_new ();
4535 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4536 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4537 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4538 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4539 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4540 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4541 gtk_widget_show_all (priority_hbox);
4542 captioned = modest_toolkit_utils_create_captioned (title_sizegroup, value_sizegroup,
4543 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4544 gtk_widget_show (captioned);
4545 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4547 /* format toggles */
4548 format_hbox = gtk_hbox_new (TRUE, 0);
4549 #ifdef MODEST_TOOLKIT_HILDON2
4550 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4552 html_toggle = gtk_toggle_button_new ();
4554 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4555 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4556 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4557 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4558 #ifdef MODEST_TOOLKIT_HILDON2
4559 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4561 text_toggle = gtk_toggle_button_new ();
4563 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4564 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4565 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4566 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4567 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4568 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4569 gtk_widget_show_all (format_hbox);
4570 gtk_widget_show (format_hbox);
4571 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4574 g_object_unref (title_sizegroup);
4575 g_object_unref (value_sizegroup);
4577 /* Set current values */
4578 switch (priv->priority_flags) {
4579 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4580 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4581 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4583 case TNY_HEADER_FLAG_LOW_PRIORITY:
4584 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4585 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4588 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4589 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4593 switch (modest_msg_edit_window_get_format (window)) {
4594 case MODEST_MSG_EDIT_FORMAT_TEXT:
4595 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4596 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4598 case MODEST_MSG_EDIT_FORMAT_HTML:
4600 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4601 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4605 /* Signal connects */
4606 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4607 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4608 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4609 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4610 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4612 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4613 GTK_WINDOW (dialog), GTK_WINDOW (window));
4615 /* Save settings if the user clicked on done */
4616 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4617 TnyHeaderFlags flags;
4618 ModestMsgEditFormat old_format, new_format;
4620 /* Set priority flags */
4621 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4622 if (priv->priority_flags != flags)
4623 modest_msg_edit_window_set_priority_flags (window, flags);
4625 /* Set edit format */
4626 old_format = modest_msg_edit_window_get_format (window);
4627 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4628 if (old_format != new_format) {
4629 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4630 modest_msg_edit_window_set_file_format (window, file_format);
4634 gtk_widget_destroy (dialog);
4635 g_slist_free (helper.priority_group);
4639 on_message_settings (GtkAction *action,
4640 ModestMsgEditWindow *window)
4642 modest_msg_edit_window_show_msg_settings_dialog (window);
4646 on_show_toolbar_button_toggled (GtkWidget *button,
4647 ModestMsgEditWindow *window)
4649 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4651 modest_msg_edit_window_show_toolbar (MODEST_WINDOW (window),
4652 modest_togglable_get_active (button));
4656 on_cc_button_toggled (GtkWidget *button,
4657 ModestMsgEditWindow *window)
4659 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4661 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4662 modest_togglable_get_active (button));
4666 on_bcc_button_toggled (GtkWidget *button,
4667 ModestMsgEditWindow *window)
4669 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4671 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4672 modest_togglable_get_active (button));
4676 setup_menu (ModestMsgEditWindow *self)
4678 ModestMsgEditWindowPrivate *priv = NULL;
4680 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4682 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4684 /* Settings menu buttons */
4685 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4686 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_check_names),
4688 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_viewer_addtocontacts"), NULL,
4689 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_add_to_contacts),
4690 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_add_to_contacts));
4691 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4692 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_undo),
4693 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4695 priv->cc_button = modest_toolkit_factory_create_check_menu (modest_runtime_get_toolkit_factory (),
4696 _("mcen_me_editor_showcc"));
4697 modest_togglable_set_active (priv->cc_button,
4699 modest_window_add_item_to_menu (MODEST_WINDOW (self), priv->cc_button, NULL);
4700 gtk_widget_show (priv->cc_button);
4701 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4702 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4704 priv->bcc_button = modest_toolkit_factory_create_check_menu (modest_runtime_get_toolkit_factory (),
4705 _("mcen_me_editor_showbcc"));
4706 gtk_widget_show (priv->bcc_button);
4707 modest_togglable_set_active (priv->bcc_button,
4709 modest_window_add_item_to_menu (MODEST_WINDOW (self), priv->bcc_button,
4711 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4712 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4714 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4715 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4716 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4717 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4718 MODEST_WINDOW_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4720 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4721 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4722 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4723 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_message_settings"), NULL,
4724 MODEST_WINDOW_MENU_CALLBACK (on_message_settings),
4726 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4727 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4730 priv->show_toolbar_button = modest_toolkit_factory_create_check_menu (modest_runtime_get_toolkit_factory (),
4731 _("mcen_bd_show_toolbar"));
4732 modest_togglable_set_active (priv->show_toolbar_button,
4734 modest_window_add_item_to_menu (MODEST_WINDOW (self), priv->show_toolbar_button,
4735 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_show_toolbar));
4736 gtk_widget_show (priv->show_toolbar_button);
4737 g_signal_connect (G_OBJECT (priv->show_toolbar_button), "toggled",
4738 G_CALLBACK (on_show_toolbar_button_toggled), (gpointer) self);
4743 emit_open_addressbook (GtkButton *button,
4744 ModestRecptEditor *editor)
4746 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4750 _create_addressbook_box (GtkSizeGroup *title_size_group,
4751 GtkSizeGroup *value_size_group,
4755 GtkWidget *abook_button;
4758 GtkWidget *label_widget;
4760 box = gtk_hbox_new (FALSE, 0);
4762 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4763 #ifndef MODEST_TOOLKIT_HILDON2
4764 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE);
4766 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4769 #ifdef MODEST_TOOLKIT_HILDON2
4770 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4772 abook_button = gtk_button_new ();
4774 label_widget = gtk_label_new (label);
4775 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4777 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4779 gtk_container_add (GTK_CONTAINER (align), abook_button);
4780 #ifdef MODEST_TOOLKIT_HILDON2
4781 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4783 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4784 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4785 if (title_size_group)
4786 #ifdef MODEST_TOOLKIT_HILDON2
4787 gtk_size_group_add_widget (title_size_group, label_widget);
4789 gtk_size_group_add_widget (title_size_group, abook_button);
4791 if (value_size_group)
4792 gtk_size_group_add_widget (value_size_group, control);
4794 g_signal_connect (G_OBJECT (abook_button), "clicked",
4795 G_CALLBACK (emit_open_addressbook), control);
4801 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4803 ModestMsgEditWindowPrivate *priv = NULL;
4805 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4807 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4808 priv->max_chars_banner = NULL;
4812 has_pending_addresses (ModestRecptEditor *recpt_editor)
4814 const gchar *recipients = NULL;
4815 GSList *start_indexes = NULL, *end_indexes = NULL;
4816 GSList *current_start, *current_end;
4817 GtkTextBuffer *buffer;
4818 gint offset_delta = 0;
4820 gboolean has_recipients_to_add = FALSE;
4822 recipients = modest_recpt_editor_get_recipients (recpt_editor);
4823 last_length = g_utf8_strlen (recipients, -1);
4824 modest_text_utils_get_addresses_indexes (recipients, &start_indexes, &end_indexes);
4829 current_start = start_indexes;
4830 current_end = end_indexes;
4831 buffer = modest_recpt_editor_get_buffer (recpt_editor);
4833 while (current_start && !has_recipients_to_add) {
4835 gchar *start_ptr, *end_ptr;
4836 gint start_pos, end_pos;
4838 start_pos = (*((gint*) current_start->data)) + offset_delta;
4839 end_pos = (*((gint*) current_end->data)) + offset_delta;
4841 start_ptr = g_utf8_offset_to_pointer (recipients, start_pos);
4842 end_ptr = g_utf8_offset_to_pointer (recipients, end_pos);
4844 address = g_strstrip (g_strndup (start_ptr, end_ptr - start_ptr));
4846 if (modest_text_utils_validate_recipient (address, NULL)) {
4847 if (!modest_address_book_has_address (address)) {
4848 has_recipients_to_add = TRUE;
4851 current_start = g_slist_next (current_start);
4852 current_end = g_slist_next (current_end);
4854 return has_recipients_to_add;
4858 modest_msg_edit_window_has_pending_addresses (ModestMsgEditWindow *self)
4860 ModestMsgEditWindowPrivate *priv = NULL;
4862 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self), FALSE);
4864 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4866 if (!has_pending_addresses ((ModestRecptEditor *) priv->to_field) &&
4867 !has_pending_addresses ((ModestRecptEditor *) priv->cc_field) &&
4868 !has_pending_addresses ((ModestRecptEditor *) priv->bcc_field))
4875 modest_msg_edit_window_set_custom_header_pairs (ModestMsgEditWindow *self,
4876 TnyList *header_pairs)
4878 ModestMsgEditWindowPrivate *priv = NULL;
4880 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
4881 g_return_if_fail (TNY_IS_LIST (header_pairs));
4883 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4884 g_object_unref (priv->custom_header_pairs);
4885 priv->custom_header_pairs = tny_list_copy (header_pairs);